diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..88902901b24bb2d891629c53de60fb0d88073ec2 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,15 @@ + + +The IF Toolset has been developed between 1998 and 2006 at VERIMAG, +an academic research laboratory in Grenoble affiliated with: + o UGA - University Grenoble Alpes, Grenoble, France + o CNRS - National Center for Scientific Research, France + o G-INP - Grenoble Institute of Technology, Grenoble, France + +The authors of the IF Toolset are: + o Marius Bozga - https://www-verimag.imag.fr/~bozga + o Iulian Ober - https://www.irit.fr/~Iulian.Ober + o Susanne Graf - https://www-verimag.imag.fr/~graf + o Laurent Mounier - https://www-verimag.imag.fr/~mounier + o Joseph Sifakis - https://www-verimag.imag.fr/~sifakis + diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000000000000000000000000000000000000..85268cf304478695e6460890020e36b02327d709 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,39 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000000000000000000000000000000000000..8a4a74b611cfb0020f90b947a7f2c1533a83f043 --- /dev/null +++ b/INSTALL @@ -0,0 +1,41 @@ +IF Installation instructions +============================= + +The current release is only supported on UNIX-like platforms. + +Please UNINSTALL all previous versions of IF before installing this version. + + +o Prerequisites + + . Install standard C++ development tools i.e., gcc, make, flex, bison, m4. + + . Install the Apache Xerces C++ XML Parser (http://xerces.apache.org/xerces-c): + + . on Linux: + $ sudo apt-get install -y libxerces-c-dev + + . on Mac, using Homebrew (see https://brew.sh): + $ brew install Xerces-C + + +o IF setup + + . Set the $IF environment variable to refer the directory + where IF software is installed (e.g. "/usr/local/IF"): + + bash : export IF=/usr/local/IF + + Add into your $PATH variable the $IF/com and $IF/bin directories: + + bash : export PATH=$PATH:$IF/com:$IF/bin + + (We recommend inserting the above definitions in the .bashrc file.) + + + +o Buiding IF binaries from source code + + $ cd src; make install + + (Cleaning object files after build: make clean) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..3ad4deaa3c84895c0ac4e6e7c74902b31d7b6e94 --- /dev/null +++ b/LICENSE @@ -0,0 +1,515 @@ + +CeCILL-B FREE SOFTWARE LICENSE AGREEMENT + + + Notice + +This Agreement is a Free Software license agreement that is the result +of discussions between its authors in order to ensure compliance with +the two main principles guiding its drafting: + + * firstly, compliance with the principles governing the distribution + of Free Software: access to source code, broad rights granted to + users, + * secondly, the election of a governing law, French law, with which + it is conformant, both as regards the law of torts and + intellectual property law, and the protection that it offers to + both authors and holders of the economic rights over software. + +The authors of the CeCILL-B (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) +license are: + +Commissariat à l'Energie Atomique - CEA, a public scientific, technical +and industrial research establishment, having its principal place of +business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. + +Centre National de la Recherche Scientifique - CNRS, a public scientific +and technological establishment, having its principal place of business +at 3 rue Michel-Ange, 75794 Paris cedex 16, France. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, a public scientific and technological establishment, having its +principal place of business at Domaine de Voluceau, Rocquencourt, BP +105, 78153 Le Chesnay cedex, France. + + + Preamble + +This Agreement is an open source software license intended to give users +significant freedom to modify and redistribute the software licensed +hereunder. + +The exercising of this freedom is conditional upon a strong obligation +of giving credits for everybody that distributes a software +incorporating a software ruled by the current license so as all +contributions to be properly identified and acknowledged. + +In consideration of access to the source code and the rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors only have limited liability. + +In this respect, the risks associated with loading, using, modifying +and/or developing or reproducing the software by the user are brought to +the user's attention, given its Free Software status, which may make it +complicated to use, with the result that its use is reserved for +developers and experienced professionals having in-depth computer +knowledge. Users are therefore encouraged to load and test the +suitability of the software as regards their requirements in conditions +enabling the security of their systems and/or data to be ensured and, +more generally, to use and operate it in the same conditions of +security. This Agreement may be freely reproduced and published, +provided it is not altered, and that no provisions are either added or +removed herefrom. + +This Agreement may apply to any or all software for which the holder of +the economic rights decides to submit the use thereof to its provisions. + + + Article 1 - DEFINITIONS + +For the purpose of this Agreement, when the following expressions +commence with a capital letter, they shall have the following meaning: + +Agreement: means this license agreement, and its possible subsequent +versions and annexes. + +Software: means the software in its Object Code and/or Source Code form +and, where applicable, its documentation, "as is" when the Licensee +accepts the Agreement. + +Initial Software: means the Software in its Source Code and possibly its +Object Code form and, where applicable, its documentation, "as is" when +it is first distributed under the terms and conditions of the Agreement. + +Modified Software: means the Software modified by at least one +Contribution. + +Source Code: means all the Software's instructions and program lines to +which access is required so as to modify the Software. + +Object Code: means the binary files originating from the compilation of +the Source Code. + +Holder: means the holder(s) of the economic rights over the Initial +Software. + +Licensee: means the Software user(s) having accepted the Agreement. + +Contributor: means a Licensee having made at least one Contribution. + +Licensor: means the Holder, or any other individual or legal entity, who +distributes the Software under the Agreement. + +Contribution: means any or all modifications, corrections, translations, +adaptations and/or new functions integrated into the Software by any or +all Contributors, as well as any or all Internal Modules. + +Module: means a set of sources files including their documentation that +enables supplementary functions or services in addition to those offered +by the Software. + +External Module: means any or all Modules, not derived from the +Software, so that this Module and the Software run in separate address +spaces, with one calling the other when they are run. + +Internal Module: means any or all Module, connected to the Software so +that they both execute in the same address space. + +Parties: mean both the Licensee and the Licensor. + +These expressions may be used both in singular and plural form. + + + Article 2 - PURPOSE + +The purpose of the Agreement is the grant by the Licensor to the +Licensee of a non-exclusive, transferable and worldwide license for the +Software as set forth in Article 5 hereinafter for the whole term of the +protection granted by the rights over said Software. + + + Article 3 - ACCEPTANCE + +3.1 The Licensee shall be deemed as having accepted the terms and +conditions of this Agreement upon the occurrence of the first of the +following events: + + * (i) loading the Software by any or all means, notably, by + downloading from a remote server, or by loading from a physical + medium; + * (ii) the first time the Licensee exercises any of the rights + granted hereunder. + +3.2 One copy of the Agreement, containing a notice relating to the +characteristics of the Software, to the limited warranty, and to the +fact that its use is restricted to experienced users has been provided +to the Licensee prior to its acceptance as set forth in Article 3.1 +hereinabove, and the Licensee hereby acknowledges that it has read and +understood it. + + + Article 4 - EFFECTIVE DATE AND TERM + + + 4.1 EFFECTIVE DATE + +The Agreement shall become effective on the date when it is accepted by +the Licensee as set forth in Article 3.1. + + + 4.2 TERM + +The Agreement shall remain in force for the entire legal term of +protection of the economic rights over the Software. + + + Article 5 - SCOPE OF RIGHTS GRANTED + +The Licensor hereby grants to the Licensee, who accepts, the following +rights over the Software for any or all use, and for the term of the +Agreement, on the basis of the terms and conditions set forth hereinafter. + +Besides, if the Licensor owns or comes to own one or more patents +protecting all or part of the functions of the Software or of its +components, the Licensor undertakes not to enforce the rights granted by +these patents against successive Licensees using, exploiting or +modifying the Software. If these patents are transferred, the Licensor +undertakes to have the transferees subscribe to the obligations set +forth in this paragraph. + + + 5.1 RIGHT OF USE + +The Licensee is authorized to use the Software, without any limitation +as to its fields of application, with it being hereinafter specified +that this comprises: + + 1. permanent or temporary reproduction of all or part of the Software + by any or all means and in any or all form. + + 2. loading, displaying, running, or storing the Software on any or + all medium. + + 3. entitlement to observe, study or test its operation so as to + determine the ideas and principles behind any or all constituent + elements of said Software. This shall apply when the Licensee + carries out any or all loading, displaying, running, transmission + or storage operation as regards the Software, that it is entitled + to carry out hereunder. + + + 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS + +The right to make Contributions includes the right to translate, adapt, +arrange, or make any or all modifications to the Software, and the right +to reproduce the resulting software. + +The Licensee is authorized to make any or all Contributions to the +Software provided that it includes an explicit notice that it is the +author of said Contribution and indicates the date of the creation thereof. + + + 5.3 RIGHT OF DISTRIBUTION + +In particular, the right of distribution includes the right to publish, +transmit and communicate the Software to the general public on any or +all medium, and by any or all means, and the right to market, either in +consideration of a fee, or free of charge, one or more copies of the +Software by any means. + +The Licensee is further authorized to distribute copies of the modified +or unmodified Software to third parties according to the terms and +conditions set forth hereinafter. + + + 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION + +The Licensee is authorized to distribute true copies of the Software in +Source Code or Object Code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the Object Code of the Software is +redistributed, the Licensee allows effective access to the full Source +Code of the Software at a minimum during the entire period of its +distribution of the Software, it being understood that the additional +cost of acquiring the Source Code shall not exceed the cost of +transferring the data. + + + 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE + +If the Licensee makes any Contribution to the Software, the resulting +Modified Software may be distributed under a license agreement other +than this Agreement subject to compliance with the provisions of Article +5.3.4. + + + 5.3.3 DISTRIBUTION OF EXTERNAL MODULES + +When the Licensee has developed an External Module, the terms and +conditions of this Agreement do not apply to said External Module, that +may be distributed under a separate license agreement. + + + 5.3.4 CREDITS + +Any Licensee who may distribute a Modified Software hereby expressly +agrees to: + + 1. indicate in the related documentation that it is based on the + Software licensed hereunder, and reproduce the intellectual + property notice for the Software, + + 2. ensure that written indications of the Software intended use, + intellectual property notice and license hereunder are included in + easily accessible format from the Modified Software interface, + + 3. mention, on a freely accessible website describing the Modified + Software, at least throughout the distribution term thereof, that + it is based on the Software licensed hereunder, and reproduce the + Software intellectual property notice, + + 4. where it is distributed to a third party that may distribute a + Modified Software without having to make its source code + available, make its best efforts to ensure that said third party + agrees to comply with the obligations set forth in this Article . + +If the Software, whether or not modified, is distributed with an +External Module designed for use in connection with the Software, the +Licensee shall submit said External Module to the foregoing obligations. + + + 5.3.5 COMPATIBILITY WITH THE CeCILL AND CeCILL-C LICENSES + +Where a Modified Software contains a Contribution subject to the CeCILL +license, the provisions set forth in Article 5.3.4 shall be optional. + +A Modified Software may be distributed under the CeCILL-C license. In +such a case the provisions set forth in Article 5.3.4 shall be optional. + + + Article 6 - INTELLECTUAL PROPERTY + + + 6.1 OVER THE INITIAL SOFTWARE + +The Holder owns the economic rights over the Initial Software. Any or +all use of the Initial Software is subject to compliance with the terms +and conditions under which the Holder has elected to distribute its work +and no one shall be entitled to modify the terms and conditions for the +distribution of said Initial Software. + +The Holder undertakes that the Initial Software will remain ruled at +least by this Agreement, for the duration set forth in Article 4.2. + + + 6.2 OVER THE CONTRIBUTIONS + +The Licensee who develops a Contribution is the owner of the +intellectual property rights over this Contribution as defined by +applicable law. + + + 6.3 OVER THE EXTERNAL MODULES + +The Licensee who develops an External Module is the owner of the +intellectual property rights over this External Module as defined by +applicable law and is free to choose the type of agreement that shall +govern its distribution. + + + 6.4 JOINT PROVISIONS + +The Licensee expressly undertakes: + + 1. not to remove, or modify, in any manner, the intellectual property + notices attached to the Software; + + 2. to reproduce said notices, in an identical manner, in the copies + of the Software modified or not. + +The Licensee undertakes not to directly or indirectly infringe the +intellectual property rights of the Holder and/or Contributors on the +Software and to take, where applicable, vis-à-vis its staff, any and all +measures required to ensure respect of said intellectual property rights +of the Holder and/or Contributors. + + + Article 7 - RELATED SERVICES + +7.1 Under no circumstances shall the Agreement oblige the Licensor to +provide technical assistance or maintenance services for the Software. + +However, the Licensor is entitled to offer this type of services. The +terms and conditions of such technical assistance, and/or such +maintenance, shall be set forth in a separate instrument. Only the +Licensor offering said maintenance and/or technical assistance services +shall incur liability therefor. + +7.2 Similarly, any Licensor is entitled to offer to its licensees, under +its sole responsibility, a warranty, that shall only be binding upon +itself, for the redistribution of the Software and/or the Modified +Software, under terms and conditions that it is free to decide. Said +warranty, and the financial terms and conditions of its application, +shall be subject of a separate instrument executed between the Licensor +and the Licensee. + + + Article 8 - LIABILITY + +8.1 Subject to the provisions of Article 8.2, the Licensee shall be +entitled to claim compensation for any direct loss it may have suffered +from the Software as a result of a fault on the part of the relevant +Licensor, subject to providing evidence thereof. + +8.2 The Licensor's liability is limited to the commitments made under +this Agreement and shall not be incurred as a result of in particular: +(i) loss due the Licensee's total or partial failure to fulfill its +obligations, (ii) direct or consequential loss that is suffered by the +Licensee due to the use or performance of the Software, and (iii) more +generally, any consequential loss. In particular the Parties expressly +agree that any or all pecuniary or business loss (i.e. loss of data, +loss of profits, operating loss, loss of customers or orders, +opportunity cost, any disturbance to business activities) or any or all +legal proceedings instituted against the Licensee by a third party, +shall constitute consequential loss and shall not provide entitlement to +any or all compensation from the Licensor. + + + Article 9 - WARRANTY + +9.1 The Licensee acknowledges that the scientific and technical +state-of-the-art when the Software was distributed did not enable all +possible uses to be tested and verified, nor for the presence of +possible defects to be detected. In this respect, the Licensee's +attention has been drawn to the risks associated with loading, using, +modifying and/or developing and reproducing the Software which are +reserved for experienced users. + +The Licensee shall be responsible for verifying, by any or all means, +the suitability of the product for its requirements, its good working +order, and for ensuring that it shall not cause damage to either persons +or properties. + +9.2 The Licensor hereby represents, in good faith, that it is entitled +to grant all the rights over the Software (including in particular the +rights set forth in Article 5). + +9.3 The Licensee acknowledges that the Software is supplied "as is" by +the Licensor without any other express or tacit warranty, other than +that provided for in Article 9.2 and, in particular, without any warranty +as to its commercial value, its secured, safe, innovative or relevant +nature. + +Specifically, the Licensor does not warrant that the Software is free +from any error, that it will operate without interruption, that it will +be compatible with the Licensee's own equipment and software +configuration, nor that it will meet the Licensee's requirements. + +9.4 The Licensor does not either expressly or tacitly warrant that the +Software does not infringe any third party intellectual property right +relating to a patent, software or any other property right. Therefore, +the Licensor disclaims any and all liability towards the Licensee +arising out of any or all proceedings for infringement that may be +instituted in respect of the use, modification and redistribution of the +Software. Nevertheless, should such proceedings be instituted against +the Licensee, the Licensor shall provide it with technical and legal +assistance for its defense. Such technical and legal assistance shall be +decided on a case-by-case basis between the relevant Licensor and the +Licensee pursuant to a memorandum of understanding. The Licensor +disclaims any and all liability as regards the Licensee's use of the +name of the Software. No warranty is given as regards the existence of +prior rights over the name of the Software or as regards the existence +of a trademark. + + + Article 10 - TERMINATION + +10.1 In the event of a breach by the Licensee of its obligations +hereunder, the Licensor may automatically terminate this Agreement +thirty (30) days after notice has been sent to the Licensee and has +remained ineffective. + +10.2 A Licensee whose Agreement is terminated shall no longer be +authorized to use, modify or distribute the Software. However, any +licenses that it may have granted prior to termination of the Agreement +shall remain valid subject to their having been granted in compliance +with the terms and conditions hereof. + + + Article 11 - MISCELLANEOUS + + + 11.1 EXCUSABLE EVENTS + +Neither Party shall be liable for any or all delay, or failure to +perform the Agreement, that may be attributable to an event of force +majeure, an act of God or an outside cause, such as defective +functioning or interruptions of the electricity or telecommunications +networks, network paralysis following a virus attack, intervention by +government authorities, natural disasters, water damage, earthquakes, +fire, explosions, strikes and labor unrest, war, etc. + +11.2 Any failure by either Party, on one or more occasions, to invoke +one or more of the provisions hereof, shall under no circumstances be +interpreted as being a waiver by the interested Party of its right to +invoke said provision(s) subsequently. + +11.3 The Agreement cancels and replaces any or all previous agreements, +whether written or oral, between the Parties and having the same +purpose, and constitutes the entirety of the agreement between said +Parties concerning said purpose. No supplement or modification to the +terms and conditions hereof shall be effective as between the Parties +unless it is made in writing and signed by their duly authorized +representatives. + +11.4 In the event that one or more of the provisions hereof were to +conflict with a current or future applicable act or legislative text, +said act or legislative text shall prevail, and the Parties shall make +the necessary amendments so as to comply with said act or legislative +text. All other provisions shall remain effective. Similarly, invalidity +of a provision of the Agreement, for any reason whatsoever, shall not +cause the Agreement as a whole to be invalid. + + + 11.5 LANGUAGE + +The Agreement is drafted in both French and English and both versions +are deemed authentic. + + + Article 12 - NEW VERSIONS OF THE AGREEMENT + +12.1 Any person is authorized to duplicate and distribute copies of this +Agreement. + +12.2 So as to ensure coherence, the wording of this Agreement is +protected and may only be modified by the authors of the License, who +reserve the right to periodically publish updates or new versions of the +Agreement, each with a separate number. These subsequent versions may +address new issues encountered by Free Software. + +12.3 Any Software distributed under a given version of the Agreement may +only be subsequently distributed under the same version of the Agreement +or a subsequent version. + + + Article 13 - GOVERNING LAW AND JURISDICTION + +13.1 The Agreement is governed by French law. The Parties agree to +endeavor to seek an amicable solution to any disagreements or disputes +that may arise during the performance of the Agreement. + +13.2 Failing an amicable solution within two (2) months as from their +occurrence, and unless emergency proceedings are necessary, the +disagreements or disputes shall be referred to the Paris Courts having +jurisdiction, by the more diligent Party. + + +Version 1.0 dated 2006-09-05. diff --git a/README b/README new file mode 100644 index 0000000000000000000000000000000000000000..9c200799b4d764f0046e99cd8844c58b42248435 --- /dev/null +++ b/README @@ -0,0 +1,29 @@ +IF Intermediate Representation +================================== + +This package contains the following software components: + + o IF front-end + o IF simulator + + + +o Installation + +See the INSTALL file for detailed installation notes. + + + +o Usage instructions + +In order to generate a simulator and simulate/verify an IF model: + + . Call the if2gen script (located $IF/com) and follow the instructions: + + $ if2gen + + . A simulation binary is generated. It's extension is .x on UNIX-like systems. + Call it for instructions on simulation/verification procedure(s). + + $ foo.x + diff --git a/README.md b/README.md deleted file mode 100644 index 0ee89138f7c89ecdf225d320df553141b04bd597..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# IF Toolset - -The open source release of the IF Toolset \ No newline at end of file diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5e7d2734cfc60289debf74293817c0a8f572ff32 --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/com/Makefile b/com/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..20d0a91b2b0fd1765dd0718567d08f307b9cb236 --- /dev/null +++ b/com/Makefile @@ -0,0 +1,63 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + + CC = g++ + + CFLAGS = -Wno-tautological-compare + + LDFLAGS = + +.SUFFIXES: +.SUFFIXES: .x .o .C .h .m4 .if + +.o.x: + $(CC) $(LDFLAGS) -o $*.x $*.o -L$(IF)/bin -lsimulator -lexplorator -lxerces-c + +.C.o: + $(CC) $(CFLAGS) -c -o $*.o -DABSTRACT -I$(IF)/src/simulator-t -I$(IF)/src/simulator $*.C + +.m4.C: + m4 -I$(IF)/src/code -D_CTYPE_=h $*.m4 > $*.h + m4 -I$(IF)/src/code -D_CTYPE_=C $*.m4 > $*.C + +clean: + -rm -f *.x *.o *.h *.C *~ + diff --git a/com/if2gen b/com/if2gen new file mode 100755 index 0000000000000000000000000000000000000000..22aec9da1286099a9e6f94ac6f34bbe64a90d3b9 --- /dev/null +++ b/com/if2gen @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +if [ x${IF:-} = x ]; then + echo "Please install IF correctly, and set the $IF environment variable" + exit 1 +fi +IFBINDIR=$IF/bin + +# +# Usage +# +if [ $# = 0 ]; then + echo "Usage: $0 [-tdiscrete | -tdbm] [-obs filename]* filename" + exit 1 +fi + +# +# if exists, move old .m4 to a tmpfile +# +for i in $*; do + IFFILE=$i +done +rm -f .tmp.*.m4 +BFILE=`basename $IFFILE .if` +TMPFILE=.tmp.`date +%s%M`.m4 +if [ -f $BFILE.m4 ]; then + mv $BFILE.m4 $TMPFILE +fi + +# +# call if2m4 with all the parameters +# +$IFBINDIR/if2m4 $* + +if [ $? = 0 -a -f $BFILE.m4 ]; then + echo "Compiled IF spec..." +else + echo "Could not compile IF spec" + if [ -f $TMPFILE ]; then + mv $TMPFILE $BFILE.m4 + fi + exit 1 +fi + +# +# compare to the old one +# +if [ -f $TMPFILE ]; then + diff $TMPFILE $BFILE.m4 >/dev/null + if [ $? = 0 ]; then + mv $TMPFILE $BFILE.m4 + fi +fi >/dev/null + +# +# make C, obj +# +make -f $IF/com/Makefile $BFILE.C +make -f $IF/com/Makefile $BFILE.o +if [ $? = 0 ]; then + echo "Compiled C++ code..." +else + exit 1 +fi + + +# +# make executable +# +make -f $IF/com/Makefile $BFILE.x + +# +# done +# + +if [ $? = 0 ]; then + echo "Done." +fi + diff --git a/doc/README b/doc/README new file mode 100644 index 0000000000000000000000000000000000000000..3b6f30a86e245e61435dc455b193a14eaed29975 --- /dev/null +++ b/doc/README @@ -0,0 +1,7 @@ + +Software documentation is being updated. + +Refer to IF/IFx website(s) for further information: + https://www-verimag.imag.fr/~async/IF + https://www.irit.fr/ifx/ + diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8c2fbe92d2be3f504246c75c0b8eb6c0ce487494 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,5 @@ +*.C +*.h +*.x +*.o +*.m4 diff --git a/examples/ackermann.if b/examples/ackermann.if new file mode 100644 index 0000000000000000000000000000000000000000..3083afd1b49bb15a9322a0c99a38307867668983 --- /dev/null +++ b/examples/ackermann.if @@ -0,0 +1,87 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +system Ackermann; + +signal result(integer); + +process ackermann(0); +fpar in m integer, in n integer, in caller pid; + +var x integer; + +state start #start ; + provided m = 0; + output result(n+1) to caller; + stop; + provided m > 0 and n = 0; + fork ackermann(m-1, 1, self); + nextstate w1; + provided m > 0 and n > 0; + fork ackermann(m, n-1, self); + nextstate w2; +endstate; + +state w2; + input result(x); + fork ackermann(m-1, x, self); + nextstate w1; +endstate; + +state w1; + input result(x); + output result(x) to caller; + stop; +endstate; +endprocess; + + +process main(1); + +state start #start ; + fork ackermann(3,5,self); + nextstate wait; +endstate; + +state wait; +endstate; + +endprocess; + +endsystem; diff --git a/examples/bitalt-o1.if b/examples/bitalt-o1.if new file mode 100644 index 0000000000000000000000000000000000000000..4f455df51de05ce376936d37aa04e208376b97b3 --- /dev/null +++ b/examples/bitalt-o1.if @@ -0,0 +1,90 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +pure observer ob; + +var b boolean := true; +var m data := 7512; +var p pid; +var si t_if_signal; + +var st t_sdt; + +state wc #start ; + /*provided ({transmitter}0) instate busy;*/ + /*provided obs_queue_length({rt}0) > 0;*/ + /*provided s = obs_queue_get_first({rt}0);*/ + /*provided (p instanceof sdt);*/ + /*provided (obs_queue_get_first({tr}0) instanceof sdt) and obs_queue_get_first({tr}0).sdt.p2 ; + task si := obs_queue_get_last({tr}0);*/ + /*provided (obs_queue_get_last({tr}0) instanceof sdt) and obs_queue_get_last({tr}0).sdt.p2 ;*/ + /*provided (obs_queue_get_at({tr}0,0) instanceof sdt) and obs_queue_get_at({tr}0,0).sdt.p2 ;*/ + /*provided (obsinput sdt in ({receiver}0)) instanceof sdt and (input sdt in ({receiver}0)).sdt.p2;*/ + /*provided (obsinput sdt) instanceof sdt and (input sdt).sdt.p2;*/ + /*provided (obsoutput sdt from ({transmitter}0) via ({tr}0) to {receiver}0) instanceof sdt;*/ + /*provided (obsoutput sdt[1]) instanceof sdt;*/ + /*provided obsfork transmitter in {receiver}0;*/ + /*provided obsfork transmitter;*/ + /*provided obskillprocess transmitter;*/ + /*provided obskillpid {transmitter}1;*/ + + + /*match input sdt(m,b) ;*/ + match input sdt(m,b) in p ; + //match input (st) in p ; + /*match input sdt(m,b) in {transmitter}0 ;*/ + /*match output sdt(m,b);*/ + /*match output sdt(m,b) from ({transmitter}0) via ({tr}0) to {receiver}0;*/ + /*match fork(p) transmitter in {transmitter}0;*/ + /*match kill(p) transmitter in {transmitter}0;*/ + /*match fork(p) transmitter in {transmitter}0;*/ + /*match deliver sdt(m,b) from {tr}0;*/ + /*match informal "a" in {transmitter}1;*/ + nextstate ctrue; +endstate; +state ctrue; + provided true; /* cuts other state successors due to observer's higher priority */ + nextstate ctrue; +endstate; +/*state c2; + match kill() transmitter in {transmitter}0; + nextstate ctrue; +endstate;*/ +endobserver; + diff --git a/examples/bitalt-o2.if b/examples/bitalt-o2.if new file mode 100644 index 0000000000000000000000000000000000000000..b3a2fc39c44f2b90551f14036fd3819d6df1604c --- /dev/null +++ b/examples/bitalt-o2.if @@ -0,0 +1,90 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +pure observer ob; + +var bi boolean; +var mi data; +var bo boolean; +var mo data; +var si t_if_signal; +var so t_if_signal; +var bd boolean; +var md data; +var sd t_if_signal; + +var p1 pid; +var p2 pid; +var p3 pid; + +state wc #start ; + //match input sdt(mi,bi) in p1 ; + match input (si) in p1 ; + informal "--input"; + nextstate -; + + match input sdt(md, bd) in p1 ; + informal "--input"; + nextstate -; + + //match output sdt(mo,bo) from p1 via p2 to p3; + match output (so) from p1 via p2 to p3; + informal "--output"; + nextstate -; + + match fork(p1) transmitter in p2; + informal "--fork"; + nextstate -; + + match kill(p1) transmitter in p2; + informal "--kill"; + nextstate -; + + match deliver sdt(md,bd) from p1; + //match deliver (sd) from p1; + informal "--deliver"; + nextstate -; + + match informal "a" in p1; + informal "--informal"; + nextstate -; +endstate; + +endobserver; + diff --git a/examples/bitalt.if b/examples/bitalt.if new file mode 100644 index 0000000000000000000000000000000000000000..994a207973c00ac322390e9ff07c0429556d90ee --- /dev/null +++ b/examples/bitalt.if @@ -0,0 +1,137 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +system bitalt; + +type data = range 0 .. 3; + +signal get(data); +signal put(data); +signal ack(boolean); +signal sdt(data, boolean); + +/* + * Connections + * + */ + +signalroute et(1) + from env to transmitter + with put; + +signalroute tr(1) #unicast #lossy + from transmitter to receiver + with sdt; + +signalroute rt(1) #unicast #lossy + from receiver to transmitter + with ack; + +signalroute re(1) + from receiver to env + with get; + +/* + * Transmitter + * + */ + +process transmitter(1); + +var t clock; +var b boolean; +var c boolean; +var m data; + +state start #start ; + task b := false; + nextstate idle; +endstate; +state idle; + input put(m); + output sdt(m, b) via {tr}0; + set t := 0; + nextstate busy; +endstate; +state busy; + input ack(c); + nextstate q8; + when t = 1; + output sdt(m, b) via {tr}0; + set t := 0; + nextstate busy; +endstate; +state q8 #unstable ; + provided c = b; + task b := not b; + reset t; + nextstate idle; + provided c <> b; + nextstate busy; +endstate; +endprocess; + +/* + * Receiver + * + */ + +process receiver(1); + +var b boolean; +var c boolean; +var m data; + +state start #start ; + task b := false; + nextstate idle; +endstate; +state idle; + input sdt(m, c); + if b = c then + output ack(b) via {rt}0; + output get(m); + task b := not b; + else + output ack(not b) via {rt}0; + endif + nextstate idle; +endstate; +endprocess; +endsystem; diff --git a/examples/earthquake.if b/examples/earthquake.if new file mode 100644 index 0000000000000000000000000000000000000000..e8bae40bc093389756fd6f571932f2e57d732015 --- /dev/null +++ b/examples/earthquake.if @@ -0,0 +1,197 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +system earthquake; + +resource CPU; +resource buffer; +resource data_exp; + +/* + * M O D E L E R + * + */ + +process modeler(1); + +var x_m clock; + +state sleeping_m #start ; + deadline eager; + informal "arrive_m"; + nextstate waiting_c; +endstate; + +state waiting_c; + deadline eager; + acquire CPU; + informal "compute"; + set x_m := 0; + nextstate computing; +endstate; + +state computing; + deadline delayable; + when x_m >= 23 and x_m <= 25; + informal "computed"; + reset x_m; + release CPU; + nextstate waiting_u; +endstate; + +state waiting_u; + deadline eager; + acquire CPU, buffer; + informal "update"; + set x_m := 0; + nextstate updating; +endstate; + +state updating; + deadline delayable; + when x_m = 10; + informal "updated"; + reset x_m; + release CPU, buffer; + task ({data}0).updated := true; + nextstate sleeping_m; +endstate; +endprocess; + +/* + * D A T A + * + */ + +process data(1); + +var updated boolean := false public; +var y clock; + +state start #start ; + set y := 0; + nextstate fresh; +endstate; + +state fresh; + deadline eager; + provided updated; + informal "refresh"; + set y := 0; + task updated := false; + nextstate fresh; + + deadline eager; + acquire data_exp; + when y >= 130; + informal "expire"; + nextstate expired; +endstate; + +state expired; + deadline eager; + provided updated; + informal "refresh"; + release data_exp; + set y := 0; + task updated := false; + nextstate fresh; +endstate; + +endprocess; + +/* + * P U L S E R + * + */ + +process pulser(1); + +var x_p clock; +var t_p clock; + +state start #start ; + set t_p := 0; + nextstate sleeping_p; +endstate; + +state sleeping_p; + deadline eager; + when t_p >= 32 and t_p <= 145; + informal "arrive_p"; + set t_p := 0; + nextstate waiting_r; +endstate; + +state waiting_r; + deadline eager; + acquire CPU, buffer, data_exp; + when t_p <= 85; + informal "read"; + set x_p := 0; + nextstate reading; + + + deadline eager; + when t_p >= 86; + informal "error"; + nextstate waiting_r; +endstate; + +state reading; + deadline delayable; + when x_p = 2 and t_p <= 87; + informal "write"; + release buffer, data_exp; + set x_p := 0; + nextstate writing; +endstate; + +state writing; + deadline delayable; + when x_p = 58 and t_p <= 145; + informal "written"; + release CPU; + reset x_p; + nextstate sleeping_p; +endstate; + +endprocess; + +endsystem; diff --git a/examples/factorial.if b/examples/factorial.if new file mode 100644 index 0000000000000000000000000000000000000000..5c69eec59ab46b496ad7cb8c500df840461b153d --- /dev/null +++ b/examples/factorial.if @@ -0,0 +1,74 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +system Factorial; + +signal result(integer); + +process factorial(0); + fpar in n integer, in caller pid; +var x integer; + +state start #start ; + provided n = 0; + output result(1) to caller; + stop; + provided n > 0; + fork factorial(n-1, self); + nextstate wait; +endstate; + +state wait; + input result(x); + output result(n*x) to caller; + stop; +endstate; +endprocess; + +process main(1); +state start #start ; + fork factorial(10, self); + nextstate wait; +endstate; + +state wait; +endstate; +endprocess; + +endsystem; diff --git a/examples/filesystem.if b/examples/filesystem.if new file mode 100644 index 0000000000000000000000000000000000000000..d7bd7d0663a299f47d862ae20f325f532a954773 --- /dev/null +++ b/examples/filesystem.if @@ -0,0 +1,191 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +system filesystem; + +const NUSERS = 2; +const NFILES = 2; + +type UserIdType = range 0 .. NUSERS; +type FileIdType = range 0 .. NFILES; +type FileStatusType = enum + Closed, Reading, Writing +endenum; +type ResponseType = enum + AcceptCommand, RejectCommand +endenum; +type ReasonType = enum + FileOpenForRead, FileOpenForWrite, FileLocked, FileClosed, FileStatusUnchanged +endenum; + +signal openForRead(FileIdType, UserIdType); +signal openForWrite(FileIdType, UserIdType); +signal close(FileIdType, UserIdType); +signal answer(ResponseType, ReasonType); + + +/* + * User Process + * + */ + +process user(NUSERS); + +var f FileIdType; +var response ResponseType; +var reason ReasonType; + +state idle #start ; + output openForRead(f, ({integer}self)) to ({filesys}0); + nextstate wait_answer; + output openForWrite(f, ({integer}self)) to ({filesys}0); + nextstate wait_answer; + output close(f, ({integer}self)) to ({filesys}0); + nextstate wait_answer; + task f := (f + 1) % NFILES; + nextstate idle; +endstate; +state wait_answer; + input answer(response, reason); + nextstate idle; +endstate; +endprocess; + +/* + * File System Process + * + */ + +process filesys(1); + +type FileControlBlockType = array [NUSERS] of FileStatusType; +type SystemStatusType = array [NFILES] of FileControlBlockType; + +var f FileIdType; +var u UserIdType; +var response ResponseType; +var reason ReasonType; +var systemStatus SystemStatusType; +var available boolean; + +procedure File_Available_For_Read; + fpar in f FileIdType, in u UserIdType, in systemStatus SystemStatusType; + returns boolean; +{# + /* files are always available for reading */ + return 1; +#} +endprocedure; + +procedure File_Available_For_Write; + fpar in f FileIdType, in u UserIdType, in systemStatus SystemStatusType; + returns boolean; +{# + /* true if nobody is updating, maybe except u */ + int uprime ; + int result=1; + for (uprime=0; uprime<if_NUSERS_constant; uprime++) + result &= (uprime==u || systemStatus[f][uprime] != if_Writing_constant); + return result; +#} +endprocedure; + + +state start #start ; + task f := 0; + while (f < NFILES) do + task u := 0; + while (u < NUSERS) do + task systemStatus[f][u] := Closed; + task u := (u + 1); + endwhile + task f := (f + 1); + endwhile + nextstate idle; +endstate; + +state idle; + input close(f, u); + task response := AcceptCommand; + if (systemStatus[f][u] <> Closed) then + task reason := FileClosed; + task systemStatus[f][u] := Closed; + else + task reason := FileStatusUnchanged; + endif + output answer(response, reason) to ({user}u); + nextstate idle; + input openForRead(f, u); + if ((systemStatus[f][u] = Reading) or + (systemStatus[f][u] = Writing)) then + task response := AcceptCommand; + task reason := FileStatusUnchanged; + else + available := call File_Available_For_Read(f,u,systemStatus); + if available then + task response := AcceptCommand; + task reason := FileOpenForRead; + task systemStatus[f][u] := Reading; + else + task response := RejectCommand; + task reason := FileLocked; + endif + endif + output answer(response, reason) to ({user}u); + nextstate idle; + input openForWrite(f, u); + if (systemStatus[f][u] = Writing) then + task response := AcceptCommand; + task reason := FileStatusUnchanged; + else + available := call File_Available_For_Write(f,u,systemStatus); + if available then + task response := AcceptCommand; + task reason := FileOpenForWrite; + task systemStatus[f][u] := Writing; + else + task response := RejectCommand; + task reason := FileLocked; + endif + endif + output answer(response, reason) to ({user}u); + nextstate idle; +endstate; +endprocess; +endsystem; diff --git a/examples/fischer.if b/examples/fischer.if new file mode 100644 index 0000000000000000000000000000000000000000..2534fd589a10a919821a7a6a03b50fcb48f3972e --- /dev/null +++ b/examples/fischer.if @@ -0,0 +1,82 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +system fischer; + +const N = 3; /* number of stations */ +const L = 2; /* waiting time */ + +process lock(1); +var p pid public; +endprocess; + +process station(N); +var c clock; +state init #start ; + deadline lazy; + provided ({lock} 0).p = nil; + set c := 0; + nextstate wait; +endstate; +state wait; + deadline delayable; + when c <= L; + task ({lock} 0).p := self; + set c := 0; + nextstate try; +endstate; +state try; + provided ({lock} 0).p = self; + when c > L; + informal "enter"; + reset c; + nextstate critical; + provided ({lock} 0).p <> self; + reset c; + nextstate init; +endstate; +state critical; + deadline lazy; + informal "exit"; + task ({lock} 0).p := nil; + nextstate init; +endstate; +endprocess; + +endsystem; diff --git a/examples/prodcons.if b/examples/prodcons.if new file mode 100644 index 0000000000000000000000000000000000000000..5922ebb95ca3292a87e122a77d8f3150c56ac315 --- /dev/null +++ b/examples/prodcons.if @@ -0,0 +1,136 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +/* + * producer / consummer + * + */ + +system pc; + +const P = 2; /* number of producers (1 or greater) */ +const C = 3; /* number of consummers (1 or greater) */ +const L = 3; /* size of the buffer (1 or greater) */ + +signal putInvoke(pid); +signal putAnswer(); +signal getInvoke(pid); +signal getAnswer(); + +/* + * producer + * + */ + +process producer(P); +state idle #start ; + output putInvoke(self) to {buffer}0; + nextstate onPut; +endstate; +state onPut; + input putAnswer(); + nextstate idle; +endstate; +endprocess; + +/* + * consummer + * + */ + +process consummer(C); +state idle #start ; + output getInvoke(self) to {buffer}0; + nextstate onGet; +endstate; +state onGet; + input getAnswer(); + nextstate idle; +endstate; +endprocess; + +/* + * buffer + * + */ + +process buffer(1); + +var c integer; +var x pid; + +state empty #start ; + save getInvoke; + input putInvoke(x); + task c := c+1; + output putAnswer() to x; + nextstate dispatch; +endstate; + +state normal; + input putInvoke(x); + task c := c+1; + output putAnswer() to x; + nextstate dispatch; + input getInvoke(x); + task c := c-1; + output getAnswer() to x; + nextstate dispatch; +endstate; + +state full; + save putInvoke; + input getInvoke(x); + task c := c-1; + output getAnswer() to x; + nextstate dispatch; +endstate; + +state dispatch #unstable ; + provided c = 0; + nextstate empty; + provided 0 < c and c < L; + nextstate normal; + provided c = L; + nextstate full; +endstate; + +endprocess; + +endsystem; \ No newline at end of file diff --git a/examples/server.if b/examples/server.if new file mode 100644 index 0000000000000000000000000000000000000000..109af288a6ffdb29bee97cfe35153269566c829f --- /dev/null +++ b/examples/server.if @@ -0,0 +1,98 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +/* + * This example describes a parallel server which can handle at + * maximum N requests simultaneously. Thus, when possible, for a + * -request- message (received from the environment) a client + * is created. The server keeps in the -i- variable the number + * of running clients. Client processes are quite simple: once + * created, they work, and when finished they send a -done- message + * back to the server. In addition, these signals are delayed + * through the signalroute cs. + * + */ + +system server_test; + +const N = 2; + +signal done(pid); +signal request(); + + +signalroute es(1) + from env to server + with request; + +signalroute cs(1) // #delay[1,2] + from client to server + with done; + + +process server(1); + +var i integer; +var x pid; + +state idle #start ; + deadline lazy; + provided (i < N); + input request(); + x := fork client(self); + task i := (i + 1); + nextstate idle; + input done(x); + task i := (i - 1); + nextstate idle; +endstate; +endprocess; + + +process client(0); + fpar parent pid; + +state init #start ; + deadline lazy; + informal "work"; + output done(self) via {cs}0 to parent; + stop; +endstate; +endprocess; +endsystem; diff --git a/examples/token.if b/examples/token.if new file mode 100644 index 0000000000000000000000000000000000000000..ba82225364e5f24b2f8aaeafe24092761563e9c9 --- /dev/null +++ b/examples/token.if @@ -0,0 +1,103 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +system token; + +const N = 2; + +signal token(); +signal claim(pid, boolean); + +signal open(integer); +signal close(integer); + +signalroute link(N) #lossy #delay[1,2] + from station to station + with token, claim; + +process station(N); + +var worried clock; +var round boolean; +var k integer; + +var a pid; +var r boolean; + +state init #start ; + task k := {integer}self; + set worried := 0; + task round := true; + nextstate wait; +endstate; +state wait; + input token(); + reset worried; + output open({integer} self); + nextstate critical; + when worried>=N+1; + set worried := 0; + output claim(self, round) via {link}k to {station}((k+1)%N); + nextstate wait; + input claim(a,r); + nextstate decision; +endstate; +state critical; + output close({integer} self); + task round := not round; + set worried := 0; + output token() via {link}k to {station}((k+1)%N); + nextstate wait; +endstate; +state decision #unstable ; + provided ({integer}a) < k; + nextstate wait; + provided ({integer}a) = k and r = round; + reset worried; + output open({integer} self); + nextstate critical; + provided ({integer}a) = k and r <> round; + nextstate wait; + provided ({integer}a) > k; + output claim(a,r) via {link}k to {station}((k+1)%N); + nextstate wait; +endstate; +endprocess; + +endsystem; diff --git a/obj/code/.gitignore b/obj/code/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5e7d2734cfc60289debf74293817c0a8f572ff32 --- /dev/null +++ b/obj/code/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/obj/model/.gitignore b/obj/model/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5e7d2734cfc60289debf74293817c0a8f572ff32 --- /dev/null +++ b/obj/model/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/obj/simulator-t/.gitignore b/obj/simulator-t/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5e7d2734cfc60289debf74293817c0a8f572ff32 --- /dev/null +++ b/obj/simulator-t/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/obj/simulator/.gitignore b/obj/simulator/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5e7d2734cfc60289debf74293817c0a8f572ff32 --- /dev/null +++ b/obj/simulator/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c8bfaf17b98b7fa9501a0ba14eed59037c77d4cf --- /dev/null +++ b/src/Makefile @@ -0,0 +1,78 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +IF = ../.. + +###################### + + LEX = flex + + YACC = bison + + CC = g++ + + CFLAGS = -c\ -Wall\ -O3 #-g + + LDFLAGS = + + AR = ar + + OBJDIR = $(IF)/obj + +###################### + + DIRS = model code simulator simulator-t + +install: + for dir in $(DIRS); do \ + ( cd $$dir; \ + echo Making $$dir ...; \ + make IF=$(IF) LEX=$(LEX) YACC=$(YACC) CC=$(CC) CFLAGS=$(CFLAGS) LDFLAGS=$(LDFLAGS) AR=$(AR) OBJDIR=$(OBJDIR)/$$dir install ) \ + done + +clean: + for dir in $(DIRS); do \ + ( cd $$dir; \ + echo Making $$dir ...; \ + make IF=$(IF) LEX=$(LEX) YACC=$(YACC) CC=$(CC) CFLAGS=$(CFLAGS) LDFLAGS=$(LDFLAGS) AR=$(AR) OBJDIR=$(OBJDIR)/$$dir clean ) \ + done + +###################### diff --git a/src/code/Makefile b/src/code/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9c62efae43ea26dfa9b8a499414eaa33884d416b --- /dev/null +++ b/src/code/Makefile @@ -0,0 +1,71 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +.SUFFIXES: +.SUFFIXES: .C .o + + SRC = if2m4.C if2if.C + + OBJ = $(OBJDIR)/if2m4.o $(OBJDIR)/if2if.o + + APP = if2m4 if2if + +######################## + +build: $(APP) + + +install: build + -mv -f $(APP) $(IF)/bin + +clean: + -rm -f $(OBJ) $(APP) + +######################## + +if2if: $(OBJDIR)/if2if.o + $(CC) -o $@ $(OBJDIR)/if2if.o -L$(IF)/bin $(LDFLAGS) -lmodel + +if2m4: $(OBJDIR)/if2m4.o + $(CC) -o $@ $(OBJDIR)/if2m4.o -L$(IF)/bin $(LDFLAGS) -lmodel + +$(OBJDIR)/%.o: %.C + $(CC) $(CFLAGS) -o $(OBJDIR)/$*.o -I../model $*.C + diff --git a/src/code/action.m4 b/src/code/action.m4 new file mode 100644 index 0000000000000000000000000000000000000000..a868b1418efdc15b94ef6b793e18a1a262dfeda4 --- /dev/null +++ b/src/code/action.m4 @@ -0,0 +1,276 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# ----------------------------------------------------------------# +# # +# Action Definitions # +# # +# ----------------------------------------------------------------# + + +# skip # + +define(`skip_body', `') + +# informal # + +define(`informal_body', `dnl + ITERATOR->trace(IfEvent::INFORMAL, m_pid, $1, m_pid, (IfObject*)$1);') + +# task # + +define(`task_body',`dnl + copy($1,$2,$3);') + +# set # + +define(`set_body', `dnl + ITERATOR->set(&$1,$2,m_pid);') + +# reset # + +define(`reset_body', `dnl + reset($1,$2);') + +# input # + +define(`input_body', `dnl + message_name($1)* x = (message_name($1)*) X; + par_cout$2 + ITERATOR->trace(IfEvent::INPUT, m_pid, x->string(), m_pid, x->store());') + +# output # + +define(`output_body', `dnl + message_name($1) x`'ifelse($2,(),,(expr$2)); + ifelse($3,0,,x.setDestination($4);) + ITERATOR->trace(IfEvent::OUTPUT, m_pid, x.string(), ifelse($3,0,$4,$3), x.store()); // anticipate the store. problem??? + ITERATOR->deliver(ifelse($3,0,$4,$3), &x);') + +# acquire + +define(`acquire_body', `dnl + int resources[] = {`resource_list($@)'}; + int enabled = ITERATOR->acquire(m_pid,resources); + if (enabled) + ITERATOR->trace(IfEvent::ACQUIRE,m_pid,"{$@}"); + return enabled;') + +# release + +define(`release_body', `dnl + int resources[] = {`resource_list($@)'}; + ITERATOR->release(m_pid,resources); + ITERATOR->trace(IfEvent::RELEASE,m_pid,"{$@}");') + +# fork # + +define(`fork_body', `dnl + ifelse($4,,type_name(pid) y;,) + ifelse($1,instance,instance_name($2), + $1,buffer,buffer_name($2),) x`'ifelse($3,(),,(expr$3)); + ITERATOR->fork(&x, &ifelse($4,,y,$4)); + ITERATOR->trace(IfEvent::FORK, m_pid, "$2", ifelse($4,,y,$4));') + +# kill # + +define(`kill_body', `dnl + unsigned pid = $1; + ITERATOR->trace(IfEvent::KILL, m_pid, "", pid); + if (m_pid != pid) + ITERATOR->kill(pid);') + +# call # + +define(`call_body',`dnl + ifelse($3,,,$3 = )procedure_name($1)(expr$2); + ITERATOR->trace(IfEvent::CALL, m_pid, "$1");') +# warning -- use copy(T)($3,...) instead of $3 = ... + +# nextstate # + +define(`nextstate_body',`dnl + ctl_assign$1 + nextstate();') + +# stop # + +define(`stop_body',`dnl + ITERATOR->kill(m_pid); + ITERATOR->step();') + +# flush # + +define(`flush_body', `dnl + IfObserverInstance::flushLabel();') + +# cut # + +define(`cut_body', `dnl + IfObserverInstance::cut();') + +# matchinput(name, (var, par, type, ...), sigvar, inpid) # + +define(`matchinput_body', `ifelse($1,,`dnl + IfMessage* x = if_obs_input_ext((unsigned)-1, $4) ; +ifelse($3,,,`dnl + $3 = x;')', + `dnl + message_name($1)* x = (message_name($1)*)if_obs_input_ext(signal_name($1), $4) ; + par_cout$2 +')') + + +# matchdiscard(name, (var, par, type, ...), sigvar, inpid) # + +define(`matchdiscard_body', `ifelse($1,,`dnl + IfMessage* x = if_obs_discard_ext((unsigned)-1, $4) ; +ifelse($3,,,`dnl + $3 = x;')', + `dnl + message_name($1)* x = (message_name($1)*)if_obs_discard_ext(signal_name($1), $4) ; + par_cout$2 +')') + + +# matchoutput(name, (var, par, type, ...), ord, sigvar, from, via, to) # + +define(`matchoutput_body', `ifelse($1,,`dnl + IfMessage* x = if_obs_output_ext((unsigned)-1, $3, $5, $6, $7) ; +ifelse($4,,,`dnl + $4 = x;')', + `dnl + message_name($1)* x = (message_name($1)*)if_obs_output_ext(signal_name($1), $3, $5, $6, $7) ; + par_cout$2')') + + +# matchfork(processname, pid, in) # + +define(`matchfork_body', `dnl + if_obs_fork_ext(ifelse($1,,(unsigned)-1,process_name($1)), $2, $3) ; +') + + +# matchkill(processname, pid, in) # + +define(`matchkill_body', `dnl + if_obs_kill_ext(ifelse($1,,(unsigned)-1,process_name($1)), $2, $3) ; +') + + +# matchdeliver(name, (var, par, type, ...), sigvar, from) # + +define(`matchdeliver_body', `ifelse($1,,`dnl + IfMessage* x = if_obs_deliver_ext(-1, $4) ; +ifelse($3,,,`dnl + $3 = x;')', + `dnl + message_name($1)* x = (message_name($1)*)if_obs_deliver_ext(signal_name($1), $4) ; + par_cout$2')') + + +# matchinformal(text, in) # + +define(`matchinformal_body', `dnl + if_obs_informal_ext($1,$2) ; +') + + +# matchprobability(pvar) # + +define(`matchprobability_body', `dnl + ifelse($1,,,$1 = )if_obs_probability_ext() ; +') + +# --------------------------------------------------------------- # + +define(`action_body', +`ifelse($1,skip,skip_body(shift($@)), + $1,informal,informal_body(shift($@)), + $1,task,task_body(shift($@)), + $1,set,set_body(shift($@)), + $1,reset,reset_body(shift($@)), + $1,input,input_body(shift($@)), + $1,output,output_body(shift($@)), + $1,acquire,acquire_body(shift($@)), + $1,release,release_body(shift($@)), + $1,fork,fork_body(shift($@)), + $1,kill,kill_body(shift($@)), + $1,call,call_body(shift($@)), + $1,flush,flush_body(shift($@)), + $1,cut,cut_body(shift($@)), + $1,matchinput,matchinput_body(shift($@)), + $1,matchdiscard,matchdiscard_body(shift($@)), + $1,matchoutput,matchoutput_body(shift($@)), + $1,matchfork,matchfork_body(shift($@)), + $1,matchkill,matchkill_body(shift($@)), + $1,matchdeliver,matchdeliver_body(shift($@)), + $1,matchinformal,matchinformal_body(shift($@)), + $1,matchprobability,matchprobability_body(shift($@)), + $1,nextstate,nextstate_body(shift($@)), + $1,stop,stop_body(shift($@)),)') + +# --------------------------------------------------------------- # + +define(`action_decl', +` inline ifelse($4,acquire,int ,void) fire_name($1,$2$3)(ifelse($4,input,IfMessage*, + $4,matchinput,IfMessage* X, + $4,matchdiscard,IfMessage* X, + $4,matchoutput,IfMessage* X, + $4,matchdeliver,IfMessage* X, + $4,matchinformal,IfMessage* X, + $4,matchfork,IfMessage* X, + $4,matchkill,IfMessage* X, + $4,matchprobability,IfMessage* X,));') + +define(`action_impl', +`inline ifelse($4,acquire,int ,void) _INSTANCE_::fire_name($1,$2$3)(ifelse($4,input,IfMessage* X, + $4,matchinput,IfMessage* X, + $4,matchdiscard,IfMessage* X, + $4,matchoutput,IfMessage* X, + $4,matchdeliver,IfMessage* X, + $4,matchinformal,IfMessage* X, + $4,matchfork,IfMessage* X, + $4,matchkill,IfMessage* X, + $4,matchprobability,IfMessage* X,)) { + +action_body(shift(shift(shift($@)))) +}') diff --git a/src/code/code.m4 b/src/code/code.m4 new file mode 100644 index 0000000000000000000000000000000000000000..8c898b453560cfc443cb04690dee966bd2d70eee --- /dev/null +++ b/src/code/code.m4 @@ -0,0 +1,90 @@ +divert(-1) + +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +# --------------------------------------------------------------- # +# global utilities # +# --------------------------------------------------------------- # +define(`m4_arg1', `$1') +define(`m4_arg2', `$2') + + +# ----------------------------------------------------------------# + +include(constant.m4) +include(type.m4) +include(variable.m4) +include(expression.m4) +include(resource.m4) +include(signal.m4) +include(signalroute.m4) +include(procedure.m4) +include(action.m4) +include(statement.m4) +include(transition.m4) +include(state.m4) +include(entity.m4) +include(obsoperations.m4) +include(priorityrule.m4) + +# ----------------------------------------------------------------# + +define(`code', +`ifelse(_CTYPE_,`h',`$1_decl(shift($@))', + _CTYPE_,`C',`$1_impl(shift($@))',)') + + +# ----------------------------------------------------------------# + +divert(1) + +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * Auto-generated simulator `code'. + * + */ + +ifelse(_CTYPE_,`C',` +`#include' <iostream> +`#include' "simulator.h" +`#include' "_FILE_`'.h" +`#include' "filter.h"') diff --git a/src/code/constant.m4 b/src/code/constant.m4 new file mode 100644 index 0000000000000000000000000000000000000000..2e7d0c5274ff0ee30568442e50bbcbe188e66d01 --- /dev/null +++ b/src/code/constant.m4 @@ -0,0 +1,63 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Constant Definitions # +# # +# --------------------------------------------------------------- # + + +# constant_name(c) # + +define(`constant_name', `if_$1_constant') # constant_name(C) # + + +# constant_decl(c,v) # + +define(`constant_decl', ` +`#define' constant_name($1) $2') + + +# constant_impl(c,v) # + +define(`constant_impl',`') + diff --git a/src/code/entity.m4 b/src/code/entity.m4 new file mode 100644 index 0000000000000000000000000000000000000000..cafa5e22649fb5339c27fa3f79f571b7ae6e1728 --- /dev/null +++ b/src/code/entity.m4 @@ -0,0 +1,848 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Ctl Helper Definitions # +# # +# --------------------------------------------------------------- # + +# ctl_input_body(s1,integer,...) + +define(`ctl_input_body', +`ifelse($2,,,`if (m_ctl.$1 != -1) + ok |= (STATE[m_ctl.$1].sigtab[signal] & 1); + ctl_input_body(shift(shift($@)))')') + +# ctl_save_body(s1,integer,...) + +define(`ctl_save_body', +`ifelse($2,,,`if (m_ctl.$1 != -1) + ok |= (STATE[m_ctl.$1].sigtab[signal] & 2); + ctl_save_body(shift(shift($@)))')') + +# ctl_is_body(s1,integer,...) + +define(`ctl_is_body', +`ifelse($2,,,`if (m_ctl.$1 != -1) + ok |= (STATE[m_ctl.$1].flags & flag); + ctl_is_body(shift(shift($@)))')') + +# ctl_tpc_body(s1,integer,...) + +define(`ctl_tpc_body', +`ifelse($2,,,`if (m_ctl.$1 != -1) + for(int sp = m_ctl.$1; ; sp = STATE[sp].parent) { + if (STATE[sp].flags & TPC) + (this->*(STATE[sp].tpc))(); + if (STATE[sp].flags & CONTROL) + break; + } + ctl_tpc_body(shift(shift($@)))')') + +# ctl_dispatch_body(s1,integer,...) + +define(`ctl_dispatch_body', +`ifelse($2,,,`if (m_ctl.$1 != -1 && (int)(STATE[m_ctl.$1].flags & UNSTABLE) == unstable) + (this->*(STATE[m_ctl.$1].dispatch))(message); + ctl_dispatch_body(shift(shift($@)))')') + +# ctl_assign(s1,v1,...) + +define(`ctl_assign', +`ifelse($2,,,`m_ctl.$1=$2; + ctl_assign(shift(shift($@)))')') + +define(`Aarg1', `$1') + +# --------------------------------------------------------------- # +# print_state(c1,int,...) # +define(`print_state', +`ifelse($1,,,`if(m_ctl.$1 != -1) { sprintf(tmp,"$1:%s,", STATE[m_ctl.$1].name); strcat(r,tmp); } + print_state(shift(shift($@)))')') + + + +# --------------------------------------------------------------- # +# # +# Instance Definitions # +# # +# --------------------------------------------------------------- # + + +define(`process_name', `if_$1_process') + +# --------------------------------------------------------------- # +# instance_name(i) # + +define(`instance_name', `if_$1_instance') + + +# --------------------------------------------------------------- # +# instance_decl(i,k, # +# (x1,T1,... ), parameters # +# (x1,T1,... ), variables # +# (x1,T1,e1, ..), var initialize # +# (c1,int,...), control # +# (...), ctl initialize # +# (s1,... )) signals # + +define(`instance_decl', ` +define(`_INSTANCE_', `instance_name($1)')dnl +/* + * $1 instance interface + * + */ + +`#define' process_name($1) $2 + +type_decl(record,$1_par,$3) + +type_decl(record,$1_var,$4) + +type_decl(record,$1_ctl,$6) + +class _INSTANCE_ : public instance_name(_SYSTEM_) { + +public: + ifelse($3,(),,_INSTANCE_`'();) + _INSTANCE_`'(var_par_decl$3); + _INSTANCE_`'(const _INSTANCE_&); + + inline int GetSP() const { return m_ctl.top; } // still used by observer operator "instate" -> only working without concurrent SMs + +public: + virtual const char* getState() const; + virtual int is(const unsigned) const; + +public: + virtual int `compare'(const IfInstance*) const; + virtual unsigned long `hash'(const unsigned long) const; + virtual IfInstance* `copy'() const; + virtual void `print'(FILE*) const; + virtual void `printXML'(std::ostream&) const; + +public: + virtual void `reset'(); + virtual void `iterate'(IfIterator*); + virtual void `copy'(const IfInstance*); + +public: + static const char* NAME; + +public: + par_export$3 + var_export$4 + +private: + declare(m_par,$1_par); /* parameters */ + declare(m_var,$1_var); /* variables */ + declare(m_ctl,$1_ctl); /* control */ + +private: + inline int input(unsigned signal) const { + int ok = 0; + ctl_input_body$6return ok; + } + inline int save(unsigned signal) const { + int ok = 0; + ctl_save_body$6return ok; + } + +private: + void fire(); +// void tpc(); + void dispatch(IfMessage*, int); + inline void nextstate();') + +# instance_table_decl(L,B) # + +# instance_table_decl(L,B) # + +define(`instance_table_decl', +`private: + typedef void (_INSTANCE_::*dispatcher)(IfMessage*); +// typedef void (_INSTANCE_::*tpcchecker)(); + static if_state<$1,dispatcher/*,tpcchecker*/> STATE[]; +') + +private: + void fire(); + inline void nextstate(int);') + +# end_instance_decl(L,B) # + +define(`end_instance_decl', `};') + + + +# --------------------------------------------------------------- # +# instance_impl(i,k, # +# (x1,T1,... ), parameters # +# (x1,T1,... ), variables # +# (x1,T1,e1, ..), var initialize # +# (c1,int,...), control # +# (...), ctl initialize # +# (s1,... )) signals # + +define(`instance_impl', ` +define(`_INSTANCE_', `instance_name($1)')dnl +/* + * $1 instance implementation + * + */ + +type_impl(record,$1_par,$3) + +type_impl(record,$1_var,$4) + +type_impl(record,$1_ctl,$6) + +const char* _INSTANCE_::NAME = IfInstance::PROCNAME[$2] = "$1"; + +ifelse($3,(),,_INSTANCE_::_INSTANCE_`'() + : instance_name(_SYSTEM_)`'(if_pid_mk(process_name($1),0), IfQueue::NIL) { + ctl_assign$7 + STATUS |= CREATE; + reset($1_var,m_var); + reset($1_par,m_par); + STATUS &= ~CREATE; + var_initialize$5 +}) + +_INSTANCE_::_INSTANCE_`'(var_par_decl$3) + : instance_name(_SYSTEM_)`'(if_pid_mk(process_name($1),0), IfQueue::NIL) { + ctl_assign$7 + STATUS |= CREATE; + reset($1_var,m_var); + ifelse($3,(),reset($1_par,m_par);,) + STATUS &= ~CREATE; + var_initialize$5 + par_cin$3 +} + +_INSTANCE_::_INSTANCE_`'(const _INSTANCE_& instance) + : instance_name(_SYSTEM_)`'(instance) { + copy($1_ctl,m_ctl,instance.m_ctl); + copy($1_var,m_var,instance.m_var); + copy($1_par,m_par,instance.m_par); +} + +const char* _INSTANCE_::`getState'() const { + static char r[1024]; + char tmp[256]; + *r = (char)0; + print_state$6 + r[strlen(r)-1]=(char)0; + return r; +} + +int _INSTANCE_::`is'(const unsigned flag) const { + int ok = 0; + ctl_is_body$6return ok; +} + +int _INSTANCE_::`compare'(const IfInstance* X) const { + _INSTANCE_* x = (_INSTANCE_*)X; + int cmp = IfInstance::`compare'(X); + if (cmp == 0) cmp = compare($1_ctl,m_ctl,x->m_ctl); + if (cmp == 0) cmp = compare($1_var,m_var,x->m_var); + if (cmp == 0) cmp = compare($1_par,m_par,x->m_par); + return cmp; +} + +unsigned long _INSTANCE_::`hash'(const unsigned long base) const { + unsigned long key = m_pid; + key += (unsigned long) m_queue; + if (sizeof(m_var) >= 4) // void + key += if_hash((char*) &m_var, sizeof(m_var), base); + if (sizeof(m_par) >= 4) // void + key += if_hash((char*) &m_par, sizeof(m_par), base); + key += if_hash((char*) &m_ctl, sizeof(m_ctl), base); + return key % base; +} + +IfInstance* _INSTANCE_::`copy'() const { + return new _INSTANCE_`'(*this); +} + +void _INSTANCE_::`print'(FILE* f) const { + // warning: `print' the topmost state name only + IfInstance::`print'(f); + fprintf(f, "\n @%s\t\t", getState()); + print($1_var,m_var,f); + fprintf(f, " "); + print($1_par,m_par,f); +} + +void _INSTANCE_::`printXML'(std::ostream& buf) const { + buf << "<IfInstance "; + buf << "type=\"$1\" "; + buf << "state=\"" << getState() << "\" >\n"; + IfInstance::`printXML'(buf); + + buf << "<var>\n"; + printXML($1_var,m_var,buf); + buf << "</var>\n"; + + buf << "<par>\n"; + printXML($1_par,m_par,buf); + buf << "</par>\n"; + buf << "</IfInstance>\n"; +} + +void _INSTANCE_::`copy'(const IfInstance* X) { + _INSTANCE_* x = (_INSTANCE_*) X; + IfInstance::`copy'(X); + copy($1_ctl,m_ctl,x->m_ctl); + copy($1_var,m_var,x->m_var); + copy($1_par,m_par,x->m_par); +} + +void _INSTANCE_::`reset'() { + reset($1_ctl,m_ctl); + ctl_assign$7 + reset($1_var,m_var); + reset($1_par,m_par); +} + +void _INSTANCE_::`iterate'(IfIterator* iterator) { + STEP = 0; + ITERATOR = iterator; + fire(); + ITERATOR = NULL; +} + + +void _INSTANCE_::fire() { + unsigned step = STEP; + +// CS: no DISCARD since it complicates everything +// if (opt_discard && (STATE[m_sp].flags & STABLE)) { +// IfMessage* message = NULL; +// for(IfQueue* queue = m_queue; +// queue != IfQueue::NIL; +// queue = (IfQueue*) queue->getTail()) { +// message = (IfMessage*) queue->getHead(); +// if (!save(message->getSid())) +// break; +// message = NULL; +// } +// if (message != NULL) { +// m_queue = m_queue->remove(message); +// if (STATE[m_sp].flags & TSIG) { +// ITERATOR->record(); +// (this->*(STATE[m_sp].dispatch))(message); +// ITERATOR->forget(); +// } +// if(STEP == step) { +// IfTime::Constraint constraints[] = {{0,0,0}}; +// ITERATOR->guard(constraints,EAGER); +// ITERATOR->trace(IfEvent::DISCARD, m_pid, message->string(), m_pid, message->store()); +// nextstate(-1); +// } +// } +// ITERATOR->restore(); +// } else { + + int unstable = is(UNSTABLE); + + if ( is(TSIG) ) { + IfMessage* message = NULL; + for(IfQueue* queue = m_queue; + queue != IfQueue::NIL; + queue = (IfQueue*) queue->getTail()) { + message = (IfMessage*) queue->getHead(); + if (!save(message->getSid())) + break; + message = NULL; + } + if (message != NULL) { + m_queue = m_queue->remove(message); + ITERATOR->record(); + dispatch(message, unstable); + ITERATOR->forget(); + } + ITERATOR->restore(); + } +// } + if ( is(TNONE) ) + dispatch(NULL, unstable); + if ( is(TSIG) ) { + fire_external_signal$8 + } + + if (is(UNSTABLE) && step == STEP) + fprintf(stderr, "\nerror #2: unstable deadlock: %s@%s\n", + NAME, getState()); +} + +void _INSTANCE_::dispatch(IfMessage* message, int unstable) { + ctl_dispatch_body$6 +} + +void _INSTANCE_::nextstate() { + + if ( !is(UNSTABLE) ) + ITERATOR->step(); + else { + ITERATOR->record(); + fire(); + ITERATOR->forget(); + } +} + +') + +# instance_table_impl(L,B) # + +define(`instance_table_impl', +`if_state<$1,_INSTANCE_::dispatcher> _INSTANCE_::STATE[] = {$2};') + +# end_instance_impl(L,B) # + +define(`end_instance_impl', `') + +# --------------------------------------------------------------- # + +define(`fire_external_signal', +`ifelse($1,,,` if (input(signal_name($1)) && !save(signal_name($1))) { + message_name($1) x; + iterate($1_par,x.m_par) + dispatch(&x,unstable); + } + fire_external_signal(shift($@))')') + +# --------------------------------------------------------------- # + + +# --------------------------------------------------------------- # +# # +# Observer Definitions # +# # +# --------------------------------------------------------------- # + + +define(`observer_name', `if_$1_observer') + +# --------------------------------------------------------------- # +# obsinstance_name(i) # + +define(`obsinstance_name', `if_$1_instance') + + +# --------------------------------------------------------------- # +# obsinstance_decl(i,k, # +# (), no parameters # +# (x1,T1,... ), variables # +# (x1,T1,e1, ..), var initialize # +# (c1,int,...), control # +# (...), ctl initialize # +# (s1,... )) signals # + +define(`obsinstance_decl', ` +define(`_INSTANCE_', `obsinstance_name($1)')dnl +/* + * $1 instance interface + * + */ + +`#define' observer_name($1) $2 + +type_decl(record,$1_var,$4) + +type_decl(record,$1_ctl,$6) + +class _INSTANCE_ : public IfObserverInstance { + +public: + ifelse($3,(),,_INSTANCE_`'();) + _INSTANCE_`'(var_par_decl$3); + _INSTANCE_`'(const _INSTANCE_&); + + inline int GetSP() const { return m_ctl.top; } // still used by observer operator "instate" -> only working without concurrent SMs + +public: + virtual const char* getState() const; + virtual int is(const unsigned) const; + +public: + virtual int `compare'(const IfInstance*) const; + virtual long unsigned `hash'(const unsigned long) const; + virtual IfInstance* `copy'() const; + virtual void `print'(FILE*) const; + virtual void `printXML'(std::ostream&) const; + +public: + virtual int isObsSuccess() const { return STATE[m_ctl.top].flags & OSUCCESS; } + virtual int isObsError() const { return STATE[m_ctl.top].flags & OERROR; } + +public: + virtual void `reset'(); + virtual void `iterate'(IfIterator*); + virtual void `copy'(const IfInstance*); + +public: + static const char* NAME; + +public: + var_export$4 + +private: + declare(m_var,$1_var); /* variables */ + declare(m_ctl,$1_ctl); /* control */ + +private: + inline int input(unsigned signal) const { + int ok = 0; + ctl_input_body$6return ok; + } + inline int save(unsigned signal) const { + int ok = 0; + ctl_save_body$6return ok; + } + +private: + void fire(); + void dispatch(IfMessage*, int); + inline void nextstate();') + +# obsinstance_table_decl(L,B) # + +define(`obsinstance_table_decl', +`private: + typedef void (_INSTANCE_::*dispatcher)(IfMessage*); + static if_state<$1,dispatcher> STATE[]; +') + +# end_obsinstance_decl(L,B) # + +define(`end_obsinstance_decl', `};') + + + +# --------------------------------------------------------------- # +# obsinstance_impl(i,k, # +# (), no parameters # +# (x1,T1,... ), variables # +# (x1,T1,e1, ..), var initialize # +# (c1,int,...), control # +# (...), ctl initialize # +# (s1,... )) signals # + +define(`obsinstance_impl', ` +define(`_INSTANCE_', `obsinstance_name($1)')dnl +/* + * $1 instance implementation + * + */ + +type_impl(record,$1_var,$4) + +type_impl(record,$1_ctl,$6) + +const char* _INSTANCE_::NAME = IfInstance::PROCNAME[$2] = "$1"; + +ifelse($3,(),,_INSTANCE_::_INSTANCE_`'() + : IfObserverInstance`'(if_pid_mk(observer_name($1),0), IfQueue::NIL) { + ctl_assign$7 + STATUS |= CREATE; + reset($1_var,m_var); + STATUS &= ~CREATE; + var_initialize$5 +}) + +_INSTANCE_::_INSTANCE_`'(var_par_decl$3) + : IfObserverInstance`'(if_pid_mk(observer_name($1),0), IfQueue::NIL) { + ctl_assign$7 + STATUS |= CREATE; + reset($1_var,m_var); + STATUS &= ~CREATE; + var_initialize$5 +} + +_INSTANCE_::_INSTANCE_`'(const _INSTANCE_& instance) + : IfObserverInstance`'(instance) { + copy($1_ctl,m_ctl,instance.m_ctl); + copy($1_var,m_var,instance.m_var); +} + +const char* _INSTANCE_::`getState'() const { + static char r[1024]; + char tmp[256]; + *r = (char)0; + print_state$6 + r[strlen(r)-1]=(char)0; + return r; +} + +int _INSTANCE_::`is'(const unsigned flag) const { + int ok = 0; + ctl_is_body$6return ok; +} + +int _INSTANCE_::`compare'(const IfInstance* X) const { + _INSTANCE_* x = (_INSTANCE_*)X; + int cmp = IfObserverInstance::`compare'(X); + if (cmp == 0) cmp = compare($1_ctl,m_ctl,x->m_ctl); + if (cmp == 0) cmp = compare($1_var,m_var,x->m_var); + return cmp; +} + +unsigned long _INSTANCE_::`hash'(const unsigned long base) const { + unsigned long key = m_pid; + key += (unsigned long) m_curLabel; + if (sizeof(m_var) >= 4) // void + key += if_hash((char*) &m_var, sizeof(m_var), base); + key += if_hash((char*) &m_ctl, sizeof(m_ctl), base); + return key % base; +} + +IfInstance* _INSTANCE_::`copy'() const { + return new _INSTANCE_`'(*this); +} + +void _INSTANCE_::`print'(FILE* f) const { + // warning: `print' the topmost state name only + IfObserverInstance::`print'(f); + fprintf(f, "\n @%s\t\t", getState()); + print($1_var,m_var,f); +} + +void _INSTANCE_::`printXML'(std::ostream& buf) const { + buf << "<IfObserverInstance "; + buf << "type=\"$1\" "; + buf << "state=\"" << getState() << "\" "; + buf << "status = \"" << (isObsError()? "error" : (isObsSuccess()? "success" : "none")) << "\" "; + buf << "cut=\"" << (m_bCut?"true":"false") << "\" >\n"; + + IfObserverInstance::`printXML'(buf); + + buf << "<var>\n"; + printXML($1_var,m_var,buf); + buf << "</var>\n"; + + buf << "</IfObserverInstance>\n"; +} + +void _INSTANCE_::`copy'(const IfInstance* X) { + _INSTANCE_* x = (_INSTANCE_*) X; + IfObserverInstance::`copy'(X); + copy($1_ctl,m_ctl,x->m_ctl); + copy($1_var,m_var,x->m_var); +} + +void _INSTANCE_::`reset'() { + reset($1_ctl,m_ctl); + ctl_assign$7 + reset($1_var,m_var); +} + +void _INSTANCE_::`iterate'(IfIterator* iter) { + STEP = 0; + ITERATOR = iter; + fire(); + ITERATOR = NULL; +} + +void _INSTANCE_::fire() { + unsigned step = STEP; + + int unstable = is(UNSTABLE); + + if ( is(TSIG) ) { + IfMessage* message = NULL; + for(IfQueue* queue = m_queue; + queue != IfQueue::NIL; + queue = (IfQueue*) queue->getTail()) { + message = (IfMessage*) queue->getHead(); + if (!save(message->getSid())) + break; + message = NULL; + } + if (message != NULL) { + m_queue = m_queue->remove(message); + ITERATOR->record(); + dispatch(message, unstable); + ITERATOR->forget(); + } + ITERATOR->restore(); + } + if ( is(TNONE) ) + dispatch(NULL, unstable); + if ( is(TSIG) ) { + fire_external_signal$8 + } + + if (is(UNSTABLE) && step == STEP) + fprintf(stderr, "\nerror #2: unstable deadlock: %s@%s\n", + NAME, STATE[m_ctl.top].name); +} + +void _INSTANCE_::dispatch(IfMessage* message, int unstable) { + ctl_dispatch_body$6 +} + +void _INSTANCE_::nextstate() { + + if ( !is(UNSTABLE) ) + ITERATOR->step(); + else { + ITERATOR->record(); + fire(); + ITERATOR->forget(); + } +} + +') + +# obsinstance_table_impl(L,B) # + +define(`obsinstance_table_impl', +`if_state<$1,_INSTANCE_::dispatcher> _INSTANCE_::STATE[] = {$2};') + +# end_obsinstance_impl(L,B) # + +define(`end_obsinstance_impl', `') + +# --------------------------------------------------------------- # +# # +# System Definitions # +# # +# --------------------------------------------------------------- # + +# +# start((route1,... routen),(proc1, ... procm),[monitor],time) +# + +define(`start_decl',`') + +define(`start_buffer', +`ifelse($1,,,`instance = new buffer_name($1); + fork(instance, &pid); + delete instance; + start_buffer(shift($@))')') + +define(`start_instance', +`ifelse($1,,,`instance = new instance_name($1); + fork(instance, &pid); + delete instance; + start_instance(shift($@))')') + +define(`start_impl', +`IfConfig* IfIterator::start() { + if_pid_type pid = 0; + IfInstance* instance = NULL; + IfConfig empty(1); + + m_config.put(&empty); + + start_buffer$1 + start_instance$2 + + ifelse($3,monitor,instance=new IfMonitor; + fork(instance, &pid); + delete instance;,) + + instance = new If`'_TIME_`'Time(); + fork(instance, &pid); + delete instance; + + // options + opt_use_priorities = x_use_priorities; + + return m_config.get(); +} +') + +# --------------------------------------------------------------- # +# +# system_instance_decl(S) +# + +define(`system_instance_decl', ` +define(`_INSTANCE_', `instance_name($1)')dnl +/* + * $1 [system] instance interface + * + */ + +class _INSTANCE_ : public IfInstance { + + public: + _INSTANCE_`'(if_pid_type = 0, IfQueue* = IfQueue::NIL); + _INSTANCE_`'(const _INSTANCE_&); + + protected: +') + +define(`end_system_instance_decl', `};') + +# --------------------------------------------------------------- # +# +# system_instance_impl(S) + + +define(`system_instance_impl',` +define(`_INSTANCE_', `instance_name($1)')dnl +/* + * $1 [system] instance implementation + * + */ + +_INSTANCE_::_INSTANCE_`'(if_pid_type pid, IfQueue* queue) + : IfInstance(pid, queue) { +} + +_INSTANCE_::_INSTANCE_`'(const _INSTANCE_& instance) + : IfInstance(instance) { +} +') + +define(`end_system_instance_impl', `') + +# --------------------------------------------------------------- # +# +# system_decl(S) + +define(`system_decl', `define(`_SYSTEM_', `$1')') + +define(`system_impl', `define(`_SYSTEM_', `$1')') diff --git a/src/code/expression.m4 b/src/code/expression.m4 new file mode 100644 index 0000000000000000000000000000000000000000..55575946f0534dc0a9ad25376a11dd19018fd0bf --- /dev/null +++ b/src/code/expression.m4 @@ -0,0 +1,85 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Operator Definitions # +# # +# --------------------------------------------------------------- # + +define(`unop',`if_$2_$1') + +define(`binop',`if_$2_$1') + +# The following `operators' must be redefined for expressions +# evaluated outside the simulator transition firing loop. +# The alternative definition is provided as a comment. + +define(`imp0rt',`((instance_name($1)*) ITERATOR->import($2))->$3()') + +# define(`imp0rt', `((instance_name($1)*) X->get($2))->$3()') + +define(`if_clock_active',`IfInstance::ITERATOR->active($1)') + +# define(`if_clock_active', `X->getTime()->active($1)') + +define(`if_clock_timeval',`IfInstance::ITERATOR->timeval($1)') + +# define(`if_clock_timeval',`X->getTime()->timeval($1)') + +define(`getStateNo',`((instance_name($1)*) ITERATOR->import($2))->GetSP()') + +# --------------------------------------------------------------- # +# # +# Expressions Definitions # +# # +# --------------------------------------------------------------- # + +define(`expr', `$@') + +# --------------------------------------------------------------- # +# # +# Constraint Definitions # +# # +# --------------------------------------------------------------- # + +define(`constraint',`{$1,$2,$3}') + diff --git a/src/code/if2if.C b/src/code/if2if.C new file mode 100644 index 0000000000000000000000000000000000000000..b3588f2d51f376325285bcb0a7d10344183d0120 --- /dev/null +++ b/src/code/if2if.C @@ -0,0 +1,110 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "model.h" + +void USAGE(char** argv) { + fprintf(stderr, "usage: %s [-obs filename]* filename\n", + argv[0]); + exit(1); +} + +#define MAXOBSEVERS 16 + +int main(int argc, char* argv[]) { + FILE* file = NULL; + IfSystemEntity* entity = NULL; + char* pszModel = NULL; + char* ppszObservers[MAXOBSEVERS]; + FILE* pfObservers[MAXOBSEVERS]; + int nObservers = 0, i; + + IfObject::Initialize(); + + if (argc == 1) { + USAGE(argv); + } + + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-') { + if(!strcmp(argv[i], "-obs")) { + i++; if(i == argc || argv[i][0] == '-') USAGE(argv); + ppszObservers[nObservers++] = argv[i]; + } + else USAGE(argv); + } else { + /* can only be the model.if */ + if(pszModel != NULL) USAGE(argv); + pszModel = argv[i]; + } + } + + // open and parse input file + file = fopen(pszModel, "r"); + if (file == NULL) { + fprintf(stderr, "error: can't open input file `%s'!\n", pszModel); + return 1; + } + + for(i = 0; i < nObservers; i++) { + pfObservers[i] = fopen(ppszObservers[i], "r"); + if (pfObservers[i] == NULL) { + fprintf(stderr, "error: can't open input file `%s'!\n", ppszObservers[i]); + return 1; + } + } + + entity = Load(file, pfObservers, nObservers); + + if (entity == NULL) { + fprintf(stderr, "error : can't parse input file `%s'!\n", argv[1]); + return 1; + } + + fclose(file); + + // dump + + entity->Dump(stdout); + + delete entity; + + return 0; +} diff --git a/src/code/if2m4.C b/src/code/if2m4.C new file mode 100644 index 0000000000000000000000000000000000000000..da9e2f19349cfe4068cbc4b0ef02aa7eeb601d94 --- /dev/null +++ b/src/code/if2m4.C @@ -0,0 +1,133 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "../model/model.h" + +void USAGE(char** argv) { + fprintf(stderr, "usage: %s [-tdiscrete | -tdbm] [-obs filename]* filename\n", + argv[0]); + exit(1); +} + +#define MAXOBSEVERS 16 + +int main(int argc, char* argv[]) { + enum {DISCRETE, DBM} time = DISCRETE; + + FILE* file = NULL; + IfSystemEntity* entity = NULL; + + char* pszModel = NULL; + char* ppszObservers[MAXOBSEVERS]; + FILE* pfObservers[MAXOBSEVERS]; + int nObservers = 0, i; + + IfObject::Initialize(); + + if (argc == 1) { + USAGE(argv); + } + + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-') { + if (!strcmp(argv[i], "-tdiscrete")) + time = DISCRETE; + else if (!strcmp(argv[i], "-tdbm")) + time = DBM; + else if(!strcmp(argv[i], "-obs")) { + i++; if(i == argc || argv[i][0] == '-') USAGE(argv); + ppszObservers[nObservers++] = argv[i]; + } + else USAGE(argv); + } else { + /* can only be the model.if */ + if(pszModel != NULL) USAGE(argv); + pszModel = argv[i]; + } + } + + // setup parse options + //opt_m4codegen = 1; + + // open and parse input file + + file = fopen(pszModel, "r"); + if (file == NULL) { + fprintf(stderr, "error: can't open input file `%s'!\n", pszModel); + return 1; + } + + for(i = 0; i < nObservers; i++) { + pfObservers[i] = fopen(ppszObservers[i], "r"); + if (pfObservers[i] == NULL) { + fprintf(stderr, "error: can't open input file `%s'!\n", ppszObservers[i]); + return 1; + } + } + + entity = Load(file, pfObservers, nObservers); + if (entity == NULL) { + fprintf(stderr, "error : can't parse input file `%s'!\n", argv[argc-1]); + return 1; + } + + fclose(file); + + // compile and generate code + + if (entity->Compile() == 0) + return 1; + + file = fopen(filename(pszModel, ".if", ".m4"), "w"); + + fprintf(file, "define(`_FILE_', `%s')\n", filename(pszModel, ".if")); + fprintf(file, "include(code.m4)\n\n"); + fprintf(file, "define(`_TIME_', `%s')\n\n", + time == DISCRETE ? "Discrete" : "Dbm"); + entity->Code(file); + + fclose(file); + + // end + + delete entity; + + return 0; +} diff --git a/src/code/obsoperations.m4 b/src/code/obsoperations.m4 new file mode 100644 index 0000000000000000000000000000000000000000..ac03ab5792af351e26cb74a3f2ed795513307c4c --- /dev/null +++ b/src/code/obsoperations.m4 @@ -0,0 +1,59 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Observer operations # +# # +# --------------------------------------------------------------- # + +# --------------------------------------------------------------- # +# obsoper_decl(ob_name) # + +define(`obsoper_decl', +`') + +# --------------------------------------------------------------- # +# obsoper_impl(ob_name) # + +define(`obsoper_impl', +`') + diff --git a/src/code/priorityrule.m4 b/src/code/priorityrule.m4 new file mode 100644 index 0000000000000000000000000000000000000000..a5cc0e9d513be440de6243c9f7603624dfc1552c --- /dev/null +++ b/src/code/priorityrule.m4 @@ -0,0 +1,73 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Priority Rule Definitions # +# # +# --------------------------------------------------------------- # + +# temporarily redefine imp0rt and getStateNo +# --------------------------------------------------------------- # +# priority_rule(procvar1, procvar2, expression, index) # + +define(`priority_rule_begin_impl',` +IfPriorityFilter::Rule* IfPriorityFilter::RULE = new IfPriorityFilter::Rule[$1]; +') + +define(`priority_rule_impl', +` +int prio_rule_function_$4(IfConfig* q,if_pid_type $2, if_pid_type $1){ + if($3) { + return 1; + } else { + return 0; + } +} + +IfPriorityFilter::Rule P$4 = IfPriorityFilter::RULE[$4] = &prio_rule_function_$4 ; +') + +define(`priority_rule_null_impl',`IfPriorityFilter::Rule P$1 = IfPriorityFilter::RULE[$1] = NULL; +') +define(`priority_rule_begin_decl',`')dnl +define(`priority_rule_decl',`')dnl +define(`priority_rule_null_decl',`')dnl diff --git a/src/code/procedure.m4 b/src/code/procedure.m4 new file mode 100644 index 0000000000000000000000000000000000000000..99582b6d0bed6c6e81d04b96cb9c404cf6168e76 --- /dev/null +++ b/src/code/procedure.m4 @@ -0,0 +1,64 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Procedure Definitions # +# # +# --------------------------------------------------------------- # + +define(`procedure_name', `$1') # procedure_name(P) # + +# --------------------------------------------------------------- # +# procedure_decl(P,E,n,(x1,T1,...xn,Tn),T,B) # + +define(`procedure_decl', +` ifelse($5,,void,type_name($5)) procedure_name($1)(var_par_decl$4);') + +# --------------------------------------------------------------- # +# procedure_impl(P,E,n,(x1,T1,...xn,Tn),T,B) # + +define(`procedure_impl', +`ifelse($5,,void,type_name($5)) instance_name($2)::procedure_name($1)(var_par_decl$4) { +$6 +}') + +# --------------------------------------------------------------- # diff --git a/src/code/resource.m4 b/src/code/resource.m4 new file mode 100644 index 0000000000000000000000000000000000000000..1df0daff6457d6fa571f7f2799299eec32d9c166 --- /dev/null +++ b/src/code/resource.m4 @@ -0,0 +1,72 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Resource Definitions # +# # +# --------------------------------------------------------------- # + + +# resource_name(r) # + +define(`resource_name', `if_$1_resource') # resource_name(r) # + + +# resource_decl(r,k) # + +define(`resource_decl', ` +static const int resource_name($1) = IfMonitor::Register($2,"$1");') + + +# resource_impl(r,k) # + +define(`resource_impl',`') + +# resource_list(r1,[r2,...]) + +define(`resource_list', +`ifelse($1,,-1,`resource_name($1),resource_list(shift($@))')') + +# resource_register(r1,[r2,...]) + +define(`resource_register', +`ifelse($1,,)') diff --git a/src/code/signal.m4 b/src/code/signal.m4 new file mode 100644 index 0000000000000000000000000000000000000000..2c6d2f397b3f63d267ca2342a70b1355ab376435 --- /dev/null +++ b/src/code/signal.m4 @@ -0,0 +1,163 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Message Definitions # +# # +# --------------------------------------------------------------- # + + +define(`signal_name', `if_$1_signal') + + +# --------------------------------------------------------------- # +# message_name(m) # + +define(`message_name', `if_$1_message') + + +# --------------------------------------------------------------- # +# message_decl(m,k,(x1,T1,... xn,Tn)) # + +define(`message_decl',` +define(`_MESSAGE_',`message_name($1)')dnl +/* + * $1 message interface + * + */ + +`#define' signal_name($1) $2 + +type_decl(record,$1_par,$3) + +class _MESSAGE_ : public IfMessage { + +public: + ifelse($3,(),,_MESSAGE_`'();) + _MESSAGE_`'(var_par_decl$3); + _MESSAGE_`'(const _MESSAGE_&); + + virtual int `compare'(const IfMessage*) const; + virtual unsigned long `hash'(const unsigned long) const; + virtual IfMessage* `copy'() const; + virtual void `print'(FILE*) const; + virtual void `printXML'(std::ostream&) const; + +public: + static const char* NAME; + +public: + declare(m_par,$1_par); + +public: + virtual int GetParSize() const { return sizeof(m_par); } + virtual void* GetParAddress() const { return (void*)&m_par; } + +}; +') + + +# --------------------------------------------------------------- # +# message_impl(m,k,(x1,T1,... xn,Tn)) # + +define(`message_impl',` +define(`_MESSAGE_',`message_name($1)')dnl +/* + * $1 message implementation + * + */ + +type_impl(record,$1_par,$3) + +const char* _MESSAGE_::NAME = IfMessage::SIGNAME[$2] = "$1"; + +ifelse($3,(),,_MESSAGE_::_MESSAGE_`'() + : IfMessage(signal_name($1)) { + reset($1_par,m_par); +} +) +_MESSAGE_::_MESSAGE_`'(var_par_decl$3) + : IfMessage(signal_name($1)) { + ifelse($3,(),reset($1_par,m_par);,par_cin$3) +} + +_MESSAGE_::_MESSAGE_`'(const _MESSAGE_& message) + : IfMessage(message) { + copy($1_par,m_par,message.m_par); +} + +int _MESSAGE_::`compare'(const IfMessage* X) const { + _MESSAGE_* x = (_MESSAGE_*)X; + int cmp = IfMessage::`compare'(X); + if (cmp == 0) cmp = compare($1_par,m_par,x->m_par); + return cmp; +} + +unsigned long _MESSAGE_::`hash'(const unsigned long base) const { + unsigned long key = IfMessage::`hash'(base); + if (sizeof(m_par) >= 4) // void + key += 17 * if_hash((char*) &m_par, sizeof(m_par), base); + return key % base; +} + +IfMessage* _MESSAGE_::`copy'() const { + return new _MESSAGE_`'(*this); +} + +void _MESSAGE_::`print'(FILE* f) const { + fprintf(f, "%s", NAME); + print($1_par,m_par,f); + IfMessage::`print'(f); +} + +void _MESSAGE_::`printXML'(std::ostream& buf) const { + buf << "<IfMessage "; + buf << "type=\"" << NAME << "\">\n"; + + buf << "<par>\n"; + printXML($1_par,m_par,buf); + buf << "</par>\n"; + + IfMessage::`printXML'(buf); + buf << "</IfMessage>\n"; +} +') diff --git a/src/code/signalroute.m4 b/src/code/signalroute.m4 new file mode 100644 index 0000000000000000000000000000000000000000..071ab03f3a9df9094f2306c61636bb3d0f1f52f2 --- /dev/null +++ b/src/code/signalroute.m4 @@ -0,0 +1,118 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Route Definitions # +# # +# --------------------------------------------------------------- # + +define(`route_name', `if_$1_route') + + +# --------------------------------------------------------------- # +# buffer_name(b) # + +define(`buffer_name', `if_$1_buffer') + + +# --------------------------------------------------------------- # +# buffer_decl(b,k,X,p1,p2,f,l,u,p) + +define(`buffer_decl', ` +define(`_BUFFER_', `buffer_name($1)')dnl +/* + * $1 buffer interface + * + */ + +`#define' route_name($1) $2 + +class _BUFFER_ : public If$3Buffer { + +public: + _BUFFER_`'(); + _BUFFER_`'(const _BUFFER_&); + +public: + virtual IfInstance* `copy'() const; + virtual void `printXML'(std::ostream&) const; + +public: + static const char* NAME; + +};') + + +# --------------------------------------------------------------- # +# buffer_decl(b,k,X,p1,p2,f,l,u,p) + +define(`buffer_impl', ` +define(`_BUFFER_', `buffer_name($1)')dnl +/* + * $1 buffer inmplementation + * + */ + +const char* _BUFFER_::NAME = IfInstance::PROCNAME[$2] = "$1"; + +_BUFFER_::_BUFFER_`'() + : If$3Buffer(if_pid_mk(process_name($4),0), if_pid_mk(process_name($5),0), + $6, $7, $8, if_pid_mk(route_name($1),0), IfQueue::NIL, $9) { +} + +_BUFFER_::_BUFFER_`'(const _BUFFER_& buffer) + : If$3Buffer(buffer) { +} + +IfInstance* _BUFFER_::`copy'() const { + return new _BUFFER_`'(*this); +} + +void _BUFFER_::`printXML'(std::ostream& buf) const { + buf << "<IfInstance "; + buf << "type=\"$1\" >\n"; + IfBuffer::`printXML'(buf); + buf << "</IfInstance>\n"; +} +') + +# --------------------------------------------------------------- # diff --git a/src/code/state.m4 b/src/code/state.m4 new file mode 100644 index 0000000000000000000000000000000000000000..255768e2fb7d84178b90718219c9287c5d520f7b --- /dev/null +++ b/src/code/state.m4 @@ -0,0 +1,92 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# State Definitions # +# # +# --------------------------------------------------------------- # + +# --------------------------------------------------------------- # +# dispatch_name(state) # + +define(`dispatch_name', `_$1_dispatch') + +# --------------------------------------------------------------- # +# message dispatcher # +# # +# dispatch(state, parent, # +# (sig1,tr11,... tr1n), # +# (sig2,tr21,... tr2m), # +# ... # +# (sigk,trk1,... trkp), # +# (,tr1,... trj)) # + +define(`dispatch_option', +`ifelse($1,,,`fire_name(_STATE_,$1)(message); + ITERATOR->restore(); + dispatch_option(shift($@))')') + +define(`dispatch_case', +`ifelse($1,, `} + else { + dispatch_option(shift($@))', + `case signal_name($1): + dispatch_option(shift($@))break;')') + +define(`dispatch_case_list', +`ifelse($1,,,`dispatch_case$1 + dispatch_case_list(shift($@))')') + +# ------ + +define(`dispatch_decl', +` void dispatch_name($1)(IfMessage*);') + +define(`dispatch_impl', +`define(`_STATE_', `$1')dnl +void _INSTANCE_::dispatch_name($1)(IfMessage* message) { + if (message != NULL) + switch(message->getSid()) { + dispatch_case_list(shift(shift($@)))} + ifelse($2,,,dispatch_name($2)(message);) +}') + diff --git a/src/code/statement.m4 b/src/code/statement.m4 new file mode 100644 index 0000000000000000000000000000000000000000..6cefb4f97f3e9ce56b6edbe63dfd7fc6ff1a8a8f --- /dev/null +++ b/src/code/statement.m4 @@ -0,0 +1,69 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# +# Statement Definitions +# +# --------------------------------------------------------------- # + +# --------------------------------------------------------------- # + +# seq_stmt_impl(stmt1, ... stmtn) + +define(`seq_stmt_impl', +`ifelse($1,,,`stmt_impl$1 +seq_stmt_impl(shift($@))')') + +# stmt_impl(stmt) + +define(`stmt_impl', +`ifelse($1,if,ifelse($2,,` fire_name(_STATE_,_TRANS_`'$1)();',` if ($2) { +seq_stmt_impl$3 } + else { +seq_stmt_impl$4 }'), + $1,while,` while ($2) { +seq_stmt_impl$3 }', + ` fire_name(_STATE_,_TRANS_`'$1)();')') + +# --------------------------------------------------------------- # + +# stmt_impl(if,x<2,((a)),((b),(c))) diff --git a/src/code/transition.m4 b/src/code/transition.m4 new file mode 100644 index 0000000000000000000000000000000000000000..ea6205ca3d85ae591e4aba9b40687a6c17b28484 --- /dev/null +++ b/src/code/transition.m4 @@ -0,0 +1,90 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Transition Definitions # +# # +# --------------------------------------------------------------- # + + +# --------------------------------------------------------------- # +# fire_name(state,index) + +define(`fire_name', `_$1_$2_fire') + +# ----------------------------------------------------------------# +# fire(state,index,deadline # +# acquire, # +# discrete-guard,(timed-constraints) # +# input,body,terminator,priority,probability,lineno) # + +define(`write_constraints', +`IfTime::Constraint constraints[] = + {$@};') + +# ------ + +define(`fire_decl', +` void fire_name($1,$2)(IfMessage*);') + +define(`fire_impl', +`void _INSTANCE_::fire_name($1,$2)(IfMessage* X) { +define(`_STATE_',`$1')dnl +define(`_TRANS_',`$2')dnl + ifelse($6,,,`write_constraints$6') + ifelse($5,,,`if (! ($5)) + return;') + ifelse($4,,,`if (! fire_name($1,$2$4)()) + return;') + ifelse($6,,,`if (! ITERATOR->guard(constraints,$3)) + return;') + if (ifelse($6,,,!constraints[0].isEmpty() || )$3!=EAGER) + if(getPriority() != OBSERVER_PRIORITY) ITERATOR->trace(IfEvent::DELTA, m_pid, ""); + ifelse($10,,,`ITERATOR->setPriority($10);') + ifelse($12,,,`if (opt_gen_lineno) ITERATOR->trace(IfEvent::DEBUG, m_pid, "$12");') + ifelse($7,,,fire_name($1,$2$7)(X);) +seq_stmt_impl$8 + ifelse($11,,,`ITERATOR->trace(IfEvent::PROBABILITY, m_pid, "", $11);') + fire_name($1,$2$9)(); + ifelse($10,,,`ITERATOR->setPriority(getPriority());') +}') + diff --git a/src/code/type.m4 b/src/code/type.m4 new file mode 100644 index 0000000000000000000000000000000000000000..0d6fea81b7a8b4602ad4a68eabd00e3e666cf7d9 --- /dev/null +++ b/src/code/type.m4 @@ -0,0 +1,588 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +define(`last_item',`ifelse($2,,$1,`last_item(shift($@))')') + +# --------------------------------------------------------------- # +# # +# Type Definitions # +# # +# --------------------------------------------------------------- # + + +define(`type_name', `if_$1_type') # type_name(T) # + + +# ----------------------------------------------------------------# +# Common Interfaces # +# ----------------------------------------------------------------# + +define(`copy_func', `if_$1_copy') +define(`copy',`copy_func($1)($2,$3)') # copy(T,x,y) # + +define(`compare_func', `if_$1_compare') +define(`compare',`compare_func($1)($2,$3)') # compare(T,x,y) # + +define(`print_func', `if_$1_print') +define(`print',`print_func($1)($2,$3)') # print(T,x,f) # + +define(`print_func_xml', `if_$1_print_xml') +define(`printXML',`print_func_xml($1)($2,$3)') # printXML(T,x,f) # + +define(`iterate_func', `if_$1_iterate') +define(`iterate',`iterate_func($1)($2)') # iterate(T,x) # + +define(`reset_func', `if_$1_reset') +define(`reset',`reset_func($1)($2)') # reset(T,x) # + + +# ----------------------------------------------------------------# +# Specific Implementations # +# ----------------------------------------------------------------# + +define(`type_decl', +`ifelse($1,enum,`enum_type_decl(shift($@))', + $1,range,`range_type_decl(shift($@))', + $1,sig_union,`sig_union_type_decl(shift($@))', + $1,record,`record_type_decl(shift($@))', + $1,array,`array_type_decl(shift($@))', + $1,string,`string_type_decl(shift($@))', + $1,tree,`tree_type_decl(shift($@))', + $1,abstract,`abstract_type_decl(shift($@))', + $1,other,`other_type_decl(shift($@))',) +`#define' if_$2_eq(x,y) compare($2,x,y)==0 +`#define' if_$2_ne(x,y) compare($2,x,y)!=0') + +define(`type_impl', +`ifelse($1,enum,`enum_type_impl(shift($@))', + $1,range,`range_type_impl(shift($@))', + $1,sig_union,`sig_union_type_impl(shift($@))', + $1,record,`record_type_impl(shift($@))', + $1,array,`array_type_impl(shift($@))', + $1,string,`string_type_impl(shift($@))', + $1,tree,`tree_type_impl(shift($@))', + $1,abstract,`abstract_type_impl(shift($@))', + $1,other,`other_type_impl(shift($@))',)') + +# ----------------------------------------------------------------# +# Enum Type # +# ----------------------------------------------------------------# + +# enum_constant(e1,... en) # + +define(`enum_constant', +`ifelse($1$2,,, + $2,,constant_name($1), + `constant_name($1), + enum_constant(shift($@))')') + +# enum_type_decl(T,e1,... en) # + +define(`enum_type_decl', ` +typedef enum { + enum_constant(shift($@)) +} type_name($1); + +extern const char* if_$1_name[]; + +`#define' copy_func($1)(x,y) (x)=(y) +`#define' compare_func($1)(x,y) (x)-(y) +`#define' print_func($1)(x,f) fprintf(f,"%s",if_$1_name[x]) +`#define' print_func_xml($1)(x,b) b << "<$1 value=\"" << if_$1_name[x] << "\" />" +`#define' reset_func($1)(x) (x)=(type_name($1))0 +`#define' iterate_func($1)(x) for(x=(type_name($1))0;x<=constant_name(last_item($@));x=(type_name($1))(x + 1))') + +# enum_quote(e1,... en) # + +define(`enum_quote', +`ifelse($1$2,,, + $2,,"$1", + `"$1", + enum_quote(shift($@))')') + +# enum_type_impl(T,e1,... en) # + +define(`enum_type_impl', ` +const char* if_$1_name[] = { + enum_quote(shift($@)) +};') + + +# ----------------------------------------------------------------# +# Range Type # +# ----------------------------------------------------------------# + +# range_type_decl(T,T1,l,u) + +define(`range_type_decl', ` +typedef type_name($2) type_name($1); + +`#define' copy_func($1)(x,y) copy_func($2)(x,y) +`#define' compare_func($1)(x,y) compare_func($2)(x,y) +`#define' print_func($1)(x,f) print_func($2)(x,f) +`#define' print_func_xml($1)(x,b) print_func_xml($2)(x,b) +`#define' reset_func($1)(x) (x)=$3 +`#define' iterate_func($1)(x) for(x=$3;x<=$4;x++)') + +# range_type_impl(T,T1,l,u) + +define(`range_type_impl', `') + + +# ----------------------------------------------------------------# +# Record Type # +# ----------------------------------------------------------------# + +# record_type(T,(x1,T1... xn,Tn)) # + +define(`record_type_decl', +`ifelse($2,,`void_record_type_decl($1)', + $2,(),`void_record_type_decl($1)', + `full_record_type_decl($1,$2)')') + +define(`record_type_impl', +`ifelse($2,,`void_record_type_impl($1)', + $2,(),`void_record_type_impl($1)', + `full_record_type_impl($1,$2)')') + + +# void_record_type(T) # + +define(`void_record_type_decl', ` +other_type_decl($1,void)') + +define(`void_record_type_impl', ` +other_type_impl($1,void)') + + +# full_record_type(T,(x1,T1... xn,Tn)) # + +define(`full_record_type_decl', ` +typedef struct { + var_var_decl$2 +} type_name($1); + +inline void copy_func($1) + (type_name($1)& x, const type_name($1) y); +inline int compare_func($1) + (const type_name($1) x, const type_name($1) y); +inline void print_func($1) + (const type_name($1) x, FILE* f); +inline void reset_func($1) + (type_name($1)& x); +`#define' iterate_func($1)(x)\ + var_iterate$2 +inline type_name($1) if_$1_make + (var_par_decl$2);') + +define(`full_record_type_impl', ` +inline void copy_func($1) + (type_name($1)& x, const type_name($1) y) { + var_copy$2 +} +inline int compare_func($1) + (const type_name($1) x, const type_name($1) y) { + int c = 0; + var_compare$2 + return c; +} +inline void print_func($1) + (const type_name($1) x, FILE* f) { + fprintf(f,"{"); + var_print$2 + fprintf(f,"}"); +} +inline void print_func_xml($1) + (const type_name($1) x, std::ostream& b) { + b << "<$1>\n"; + var_print_xml$2 + b << "</$1>\n"; +} +inline void reset_func($1) + (type_name($1)& x) { + var_reset$2 +} + +inline type_name($1) if_$1_make + (var_par_decl$2) { + type_name($1) m_par; + par_cin$2 + return m_par; +}') + +# ----------------------------------------------------------------# +# SignalUnion Type # +# ----------------------------------------------------------------# + +# sig_union_type(T,(x1,T1... xn,Tn)) # + +define(`sig_union_type_decl', ` +typedef IfMessage* type_name($1); +') + +define(`sig_union_type_impl', ` +inline void copy_func($1) + (type_name($1)& x, const type_name($1) y) { + x = y; +} +inline int compare_func($1) + (const type_name($1) x, const type_name($1) y) { + int c = x - y; + if(c || x == NULL) return c; + return x->`compare'(y); +} +inline void print_func($1) + (const type_name($1) x, FILE* f) { + fprintf(f,"{"); + if(x) x->`print'(f); + else fprintf(f,"nil"); + fprintf(f,"}"); +} +inline void print_func_xml($1) + (const type_name($1) x, std::ostream& b) { + b << "<sigunion>\n"; + if(x) x->`printXML'(b); + b << "</sigunion>\n"; +} +inline void reset_func($1) + (type_name($1)& x) { + x = NULL; +} +') + +# ----------------------------------------------------------------# +# Array Type # +# ----------------------------------------------------------------# + +define(`array_iterate', +`ifelse($2,0,` iterate_func($1)(x[$2])', ` iterate_func($1)(x[$2])\ +array_iterate($1,decr($2))')') + +# array_type_decl(T,T1,n,k) k=(int)n + +define(`array_type_decl', ` +typedef type_name($2) type_name($1)[$3]; + +inline void copy_func($1) + (type_name($1)& x, const type_name($1) y); +inline int compare_func($1) + (const type_name($1) x, const type_name($1) y); +inline void print_func($1) + (const type_name($1) x, FILE* f); +inline void reset_func($1) + (type_name($1)& x); +`#define' iterate_func($1)(x)\ +array_iterate($2,decr($4))') + +# array_type_decl(T,T1,n,k) k=(int)n + +define(`array_type_impl', ` +inline void copy_func($1) + (type_name($1)& x, const type_name($1) y) { + for(int i=0;i<$3;i++) + copy_func($2)(x[i],y[i]); +} +inline int compare_func($1) + (const type_name($1) x, const type_name($1) y) { + int c = 0; + for(int i=0;i<$3 && !c;i++) + c = compare_func($2)(x[i],y[i]); + return c; +} +inline void print_func($1) + (const type_name($1) x, FILE* f) { + fprintf(f,"{"); + for(int i=0;i<$3;i++) { + print_func($2)(x[i],f); + fprintf(f,","); + } + fprintf(f,"}"); +} +inline void print_func_xml($1) + (const type_name($1) x, std::ostream& b) { + b << "<array>\n"; + for(int i=0;i<$3;i++) { + print_func_xml($2)(x[i],b); + } + b << "</array>\n"; +} +inline void reset_func($1) + (type_name($1)& x) { + for(int i=0;i<$3;i++) + reset_func($2)(x[i]); +}') + + +# ----------------------------------------------------------------# +# String Type # +# ----------------------------------------------------------------# + +# string_type_decl(T,T1,n) + +define(`string_type_decl', ` +struct type_name($1) { + int length; + type_name($2) elem[$3]; + + type_name($2)& operator[](const int i) + { return elem[i]; } +}; + +inline void copy_func($1) + (type_name($1)& x, const type_name($1) y); +inline int compare_func($1) + (const type_name($1) x, const type_name($1) y); +inline void print_func($1) + (const type_name($1) x, FILE* f); +inline void reset_func($1) + (type_name($1)& x); +inline int if_$1_length + (const type_name($1) x); +type_name($1) if_$1_make + (); +type_name($1) if_$1_make + (const type_name($2) e); +type_name($1) if_$1_concat + (const type_name($1) x, const type_name($1) y); +type_name($1) if_$1_substring + (const type_name($1) x, const int k, const int l); +type_name($1) if_$1_remove + (const type_name($1) x, const int k); +type_name($1) if_$1_insert + (const type_name($1) x, const int k, const type_name($2) e); +int if_$1_`index' + (const type_name($1) x, const type_name($2) e);') + +# string_type_impl(T,T1,n) + +define(`string_type_impl', ` +inline void copy_func($1) + (type_name($1)& x, const type_name($1) y) { + reset_func($1)(x); + for(int i=0;i<y.length;i++) + copy_func($2)(x.elem[i],y.elem[i]); + x.length=y.length; +} +inline int compare_func($1) + (const type_name($1) x, const type_name($1) y) { + int c = x.length-y.length; + for(int i=0;i<x.length && !c;i++) + c = compare_func($2)(x.elem[i],y.elem[i]); + return c; +} +inline void print_func($1) + (const type_name($1) x, FILE* f) { + fprintf(f,"{"); + for(int i=0;i<x.length;i++) { + print_func($2)(x.elem[i],f); + fprintf(f,","); + } + fprintf(f,"}"); +} +inline void print_func_xml($1) + (const type_name($1) x, std::ostream& b) { + b << "<string>\n"; + for(int i=0;i<x.length;i++) { + print_func_xml($2)(x.elem[i],b); + } + b << "</string>\n"; +} +inline void reset_func($1) + (type_name($1)& x) { + x.length=0; + for(int i=0;i<$3;i++) + reset_func($2)(x.elem[i]); +} + +inline int if_$1_length + (const type_name($1) x) { + return x.length; +} +type_name($1) if_$1_make + () { + type_name($1) z; + reset_func($1)(z); + return z; +} +type_name($1) if_$1_make + (const type_name($2) e) { + type_name($1) z; + reset_func($1)(z); + if (0<$3) { + copy_func($2)(z.elem[0],e); + z.length=1; + } + return z; +} +type_name($1) if_$1_concat + (const type_name($1) x, const type_name($1) y) { + type_name($1) z; + reset_func($1)(z); + int i; + + for(i=0;i<x.length && z.length<$3;i++,z.length++) + copy_func($2)(z.elem[z.length],x.elem[i]); + for(i=0;i<y.length && z.length<$3;i++,z.length++) + copy_func($2)(z.elem[z.length],y.elem[i]); + return z; +} +type_name($1) if_$1_substring + (const type_name($1) x, const int k, const int l) { + type_name($1) z; + reset_func($1)(z); + for(int i=k;i<=l && + i<x.length && z.length<$3; i++,z.length++) + copy_func($2)(z.elem[z.length], x.elem[i]); + return z; +} +type_name($1) if_$1_remove + (const type_name($1) x, const int k) { + type_name($1) z; + reset_func($1)(z); + if (0<=k && k<x.length) + for(int i=0;i<x.length;i++,z.length++) { + copy_func($2)(z.elem[z.length],x.elem[i]); + if (i==k) z.length--; + } + else + copy_func($1)(z,x); + return z; +} +type_name($1) if_$1_insert + (const type_name($1) x, const int k, const type_name($2) e) { + type_name($1) z; + reset_func($1)(z); + if (0<=k && k<=x.length && x.length<$3) { + int i; + for(i=0;i<k;i++,z.length++) + copy_func($2)(z.elem[z.length],x.elem[i]); + copy_func($2)(z.elem[z.length++],e); + for(i=k;i<x.length;i++,z.length++) + copy_func($2)(z.elem[z.length],x.elem[i]); + } + else + copy_func($1)(z,x); + return z; +} +int if_$1_`index' + (const type_name($1) x, const type_name($2) e) { + int idx = -1; + for(int i=0;i<x.length && idx<0;i++) + if (compare_func($2)(x.elem[i],e)==0) + idx = i; + return idx; +}') + + +# ----------------------------------------------------------------# +# Tree Type # +# ----------------------------------------------------------------# + +# tree_type_decl(T,T1,r,h) + +define(`tree_type_decl', ` +/* tree type : not yet implemented */ +') + +# tree_type_impl(T,T1,r,h) + +define(`tree_type_impl', ` +/* tree type : not yet implemented */ +') + + +# ----------------------------------------------------------------# +# Abstract Type # +# ----------------------------------------------------------------# + +define(`function_name', `if_$1_function') # function_name(C) # + +# function_decl(f,(x1,T1,...xn,Tn),Tr) # + +define(`function_decl',`type_name($3) function_name($1)(var_par_decl$2);') + +# function_impl(f,(x1,T1,...xn,Tn),Tr) # + +define(`function_impl',`') + + + +# abstract_type_decl(T) # + +define(`abstract_type_decl', ` +`#ifndef' ABSTRACT +typedef char* type_name($1); + +`#define' copy_func($1)(x,y) (x)=(y) +`#define' compare_func($1)(x,y) (x)-(y) +`#define' print_func($1)(x,f) fprintf(f,"%#x",(unsigned)x) +`#define' print_func_xml($1)(x,b) b << "<$1 value=\"" << x << "\" />" +`#define' reset_func($1)(x) (x)=NULL +`#else' +`#define' __$1__ +`#include' "_FILE_.i" +`#undef' __$1__ +`#endif'') + +# abstract_type_impl(T) # + +define(`abstract_type_impl', `') + + +# ----------------------------------------------------------------# +# Other Type # +# ----------------------------------------------------------------# + +# other_type_decl(T1,T2) # + +define(`other_type_decl', ` +typedef type_name($2) type_name($1); + +`#define' copy_func($1)(x,y) copy_func($2)(x,y) +`#define' compare_func($1)(x,y) compare_func($2)(x,y) +`#define' print_func($1)(x,f) print_func($2)(x,f) +`#define' print_func_xml($1)(x,b) print_func_xml($2)(x,b) +`#define' reset_func($1)(x) reset_func($2)(x) +`#define' iterate_func($1)(x) iterate_func($2)(x)') + +# other_type_impl(T1,T2) # + +define(`other_type_impl', `') diff --git a/src/code/variable.m4 b/src/code/variable.m4 new file mode 100644 index 0000000000000000000000000000000000000000..243909591492facecd6b224c230674b092ab0cd4 --- /dev/null +++ b/src/code/variable.m4 @@ -0,0 +1,169 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + + +# --------------------------------------------------------------- # +# # +# Variable Definitions # +# # +# --------------------------------------------------------------- # + + +# ----------------------------------------------------------------# +# Declarations # +# ----------------------------------------------------------------# + +# declare(x,T) # + +define(`declare',`type_name($2) $1') + +# var_par_decl(x1,T1,...,xn,Tn) # + +define(`var_par_decl', +`ifelse($2$4,,, + $4,,declare($1,$2), + `declare($1,$2),var_par_decl(shift(shift($@)))')') + +# var_var_decl(x1,T1,... xn,Tn) # + +define(`var_var_decl', +`ifelse($2$4,,, + $4,,declare($1,$2);, + `declare($1,$2); + var_var_decl(shift(shift($@)))')') + + +# ----------------------------------------------------------------# +# Structure Implementation # +# ----------------------------------------------------------------# + +# var_copy(x1,T1,...xn,Tn) # + +define(`var_copy', +`ifelse($2$4,,, + $4,,copy($2,x.$1,y.$1);, + `copy($2,x.$1,y.$1); + var_copy(shift(shift($@)))')') + + +# var_compare(x1,T1,...xn,Tn) # + +define(`var_compare', +`ifelse($2$4,,, + $4,,if (c == 0) c = compare($2,x.$1,y.$1);, + `if (c == 0) c = compare($2,x.$1,y.$1); + var_compare(shift(shift($@)))')') + +# var_print(x1,T1,...xn,Tn) # + +define(`var_print', +`ifelse($2$4,,, + $4,,fprintf(f,"$1="); print($2,x.$1,f);, + `fprintf(f,"$1="); print($2,x.$1,f); fprintf(f,","); + var_print(shift(shift($@)))')') + +# var_print_xml(x1,T1,...xn,Tn) # + +define(`var_print_xml', +`ifelse($2$4,,, + $4,,b << "<$1>"; printXML($2,x.$1,b); b << "</$1>"; , + `b << "<$1>"; printXML($2,x.$1,b); b << "</$1>"; + var_print_xml(shift(shift($@)))')') + +# var_reset(x1,T1,...xn,Tn) # + +define(`var_reset', +`ifelse($2$4,,, + $4,,reset($2,x.$1);, + `reset($2,x.$1); + var_reset(shift(shift($@)))')') + +# var_iterate(x1,T1,...xn,Tn) # + +define(`var_iterate', +`ifelse($2$4,,, + $4,,iterate($2,x.$1), + `iterate($2,x.$1)\ + var_iterate(shift(shift($@)))')') + + +# ----------------------------------------------------------------# + +# var_export(x1,T1,... xn,Tn) + +define(`var_export', +`ifelse($2,,,`inline type_name($2)& `$1'() + { return m_var.$1; } + var_export(shift(shift($@)))')') + +# var_initialize(x1,T1,e1,... xn,Tn,en) + +define(`var_initialize', +`ifelse($3,,,`copy($2,m_var.$1,$3); + var_initialize(shift(shift(shift($@))))')') + +# ----------------------------------------------------------------# + +# par_export(x1,T1,... xn, Tn) + +define(`par_export', +`ifelse($2,,,`inline type_name($2)& `$1'() + { return m_par.$1; } + par_export(shift(shift($@)))')') + +# ----------------------------------------------------------------# + +# par_cin(x1,T1,... xn,Tn) # + +define(`par_cin', +`ifelse($2$4,,, + $4,,copy($2,m_par.$1,$1);, + `copy($2,m_par.$1,$1); + par_cin(shift(shift($@)))')') + +# par_cout(x1,p1,T1,... xn,pn,Tn) # + +define(`par_cout', +`ifelse($3$6,,, + $6,,copy($3,$1,x->m_par.$2);, + `copy($3,$1,x->m_par.$2); + par_cout(shift(shift(shift($@))))')') + + diff --git a/src/model/.gitignore b/src/model/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..edb0cc337c3395bad8318a521b1bbdbf71642581 --- /dev/null +++ b/src/model/.gitignore @@ -0,0 +1,3 @@ +if.lex.i +if.yacc.C +if.yacc.H diff --git a/src/model/Makefile b/src/model/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..689ceef530829fb3e684924e90dc404c25836e41 --- /dev/null +++ b/src/model/Makefile @@ -0,0 +1,110 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +.SUFFIXES: +.SUFFIXES: .C .i .l .y .o + + SRC = object.C \ + constant.C \ + type.C \ + variable.C \ + expression.C \ + constraint.C \ + resource.C \ + signal.C \ + signalroute.C \ + procedure.C \ + action.C \ + statement.C \ + transition.C \ + state.C \ + entity.C \ + priorityrule.C \ + if.yacc.y + + OBJ = $(OBJDIR)/object.o \ + $(OBJDIR)/constant.o \ + $(OBJDIR)/type.o \ + $(OBJDIR)/variable.o \ + $(OBJDIR)/expression.o \ + $(OBJDIR)/constraint.o \ + $(OBJDIR)/signal.o \ + $(OBJDIR)/resource.o \ + $(OBJDIR)/signalroute.o \ + $(OBJDIR)/procedure.o \ + $(OBJDIR)/action.o \ + $(OBJDIR)/statement.o \ + $(OBJDIR)/transition.o \ + $(OBJDIR)/state.o \ + $(OBJDIR)/priorityrule.o \ + $(OBJDIR)/entity.o \ + $(OBJDIR)/model.o \ + $(OBJDIR)/if.yacc.o + + LIB = libmodel.a + +############### + +build: $(LIB) + + +install: build + -mv -f $(LIB) $(IF)/bin + +clean: + -rm -f if.lex.i if.yacc.H if.yacc.C $(OBJ) $(LIB) + +############### + +$(LIB): $(OBJ) + $(AR) cql $@ $(OBJ) + +$(OBJDIR)/%.o: %.C + $(CC) $(CFLAGS) -o $(OBJDIR)/$*.o $*.C + +.l.i: + $(LEX) -o$*.i $*.l + +.y.C: + $(YACC) -d -o $*.C $*.y + +########################## + +$(OBJDIR)/if.yacc.o: if.yacc.C if.lex.i diff --git a/src/model/action.C b/src/model/action.C new file mode 100644 index 0000000000000000000000000000000000000000..f00db3d1b823142982b713bcd712d7edd77d0609 --- /dev/null +++ b/src/model/action.C @@ -0,0 +1,1741 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of actions + * + */ + +#include "model.h" + +IfTransition* IfAction::TRANSITION = NULL; + +IfAction::IfAction(unsigned Flags) + : IfObject(NULL, Flags) { +} + +void IfAction::PreCompile() { + IfObject::PreCompile(); +} + +void IfAction::Alpha(FILE* file) const { + int index = m_iIndex; + do { + fprintf(file, "%c", 'a'+ index % 26); + index /= 26; + } while (index); +} + +void IfAction::Code(FILE* file) const { + fprintf(file, "code(action,%s,%d,", + TRANSITION->GetSource()->GetName(), + TRANSITION->GetIndex()); + Alpha(file); + fprintf(file, ",\n\t"); +} + +int IfAction::Use(const IfVariable* Variable) const { + // pure virtual + return 0; +} + +int IfAction::Def(const IfVariable* Variable) const { + // pure virtual + return 0; +} + +/* + * + * skip action + * + */ + +IfSkipAction::IfSkipAction(unsigned Flags) + : IfAction(Flags) { +} + +void IfSkipAction::Dump(FILE* file) const { + fprintf(file, "skip;"); +} + +void IfSkipAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "skip)"); +} + +int IfSkipAction::Use(const IfVariable* Variable) const { + return 0; +} + +int IfSkipAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * informal action + * + */ + +IfInformalAction::IfInformalAction(char* Informal, + unsigned Flags) + : IfAction(Flags) { + m_pInformal = Informal; +} + +IfInformalAction::~IfInformalAction() { + free(m_pInformal); +} + +void IfInformalAction::Dump(FILE* file) const { + fprintf(file, "informal %s;", m_pInformal); +} + +void IfInformalAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "informal,%s)", m_pInformal); +} + +int IfInformalAction::Use(const IfVariable* Variable) const { + return 0; +} + +int IfInformalAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * task action + * + */ + +IfTaskAction::IfTaskAction(IfExpression* Lhs, + IfExpression* Rhs, + unsigned Flags) + : IfAction(Flags) { + m_pLhs = Lhs; + m_pRhs = Rhs; +} + +IfTaskAction::~IfTaskAction() { + delete m_pLhs; + delete m_pRhs; +} + +void IfTaskAction::Dump(FILE* file) const { + fprintf(file, "task "); + m_pLhs->Dump(file); + fprintf(file, " := "); + m_pRhs->Dump(file); + fprintf(file, ";"); +} + +void IfTaskAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + ok &= m_pLhs->Compile(); + ok &= m_pLhs->IsReference(); + ok &= m_pRhs->Compile(); + ok &= m_pRhs->Match(m_pLhs->GetType()); + + //ok &= !m_pLhs->IsTimed(); + //ok &= !m_pRhs->IsTimed(); + + SetFlag(CORRECT, ok); +} + +void IfTaskAction::Code(FILE* file) const { + IfAction::Code(file); + + fprintf(file, "task,%s,", m_pLhs->GetType()->GetName()); + m_pLhs->Code(file); + fprintf(file, ","); + m_pRhs->Code(file); + fprintf(file, ")"); +} + +int IfTaskAction::Use(const IfVariable* Variable) const { + return + m_pRhs->Use(Variable) || + (m_pLhs->Use(Variable) && !m_pLhs->IsVariable()); +} + +int IfTaskAction::Def(const IfVariable* Variable) const { + return + m_pLhs->Def(Variable); +} + +/* + * + * set action + * + */ + +IfSetAction::IfSetAction(IfExpression* Lhs, + IfExpression* Rhs, + unsigned Flags) + : IfAction(Flags) { + m_pLhs = Lhs; + m_pRhs = Rhs; +} + +IfSetAction::~IfSetAction() { + delete m_pLhs; + delete m_pRhs; +} + +void IfSetAction::Dump(FILE* file) const { + fprintf(file, "set "); + m_pLhs->Dump(file); + fprintf(file, " := "); + m_pRhs->Dump(file); + fprintf(file, ";"); +} + +void IfSetAction::PreCompile() { + IfAction::PreCompile(); + + IfBasicType* clock = TYPES[IfBasicType::CLOCK]; + IfBasicType* integer = TYPES[IfBasicType::INTEGER]; + + int ok = 1; + + ok &= m_pLhs->Compile(); + ok &= m_pLhs->IsReference(); + if (m_pLhs->GetType()) + ok &= m_pLhs->GetType()->Match(clock); + + ok &= m_pRhs->Compile(); + if (m_pRhs->GetType()) + ok &= m_pRhs->GetType()->Match(integer); + + SetFlag(CORRECT, ok); +} + +void IfSetAction::Code(FILE* file) const { + IfAction::Code(file); + + fprintf(file, "set,"); + m_pLhs->Code(file); + fprintf(file, ","); + m_pRhs->Code(file); + fprintf(file, ")"); +} + +int IfSetAction::Use(const IfVariable* Variable) const { + return + m_pRhs->Use(Variable) || + (m_pLhs->Use(Variable) && !m_pLhs->IsVariable()); +} + +int IfSetAction::Def(const IfVariable* Variable) const { + return + m_pLhs->Def(Variable); +} + +/* + * + * reset action + * + */ + +IfResetAction::IfResetAction(IfExpression* Lhs, + unsigned Flags) + : IfAction(Flags) { + m_pLhs = Lhs; +} + +IfResetAction::~IfResetAction() { + delete m_pLhs; +} + +void IfResetAction::Dump(FILE* file) const { + fprintf(file, "reset "); + m_pLhs->Dump(file); + fprintf(file, ";"); +} + +void IfResetAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + ok &= m_pLhs->Compile(); + ok &= m_pLhs->IsReference(); + + SetFlag(CORRECT, ok); +} + +void IfResetAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "reset,%s,", m_pLhs->GetType()->GetName()); + m_pLhs->Code(file); + fprintf(file, ")"); +} + +int IfResetAction::Use(const IfVariable* Variable) const { + return + m_pLhs->Use(Variable) && !m_pLhs->IsVariable(); +} + +int IfResetAction::Def(const IfVariable* Variable) const { + return + m_pLhs->Def(Variable); +} + +/* + * + * input action + * + */ + +IfInputAction::IfInputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + unsigned Flags) + : IfAction(Flags) { + m_pSignal = Signal; + m_pParameters = Parameters; +} + +IfInputAction::~IfInputAction() { + delete m_pParameters; +} + +void IfInputAction::Dump(FILE* file) const { + fprintf(file, "input %s(", m_pSignal->GetName()); + m_pParameters->Dump(file, "", ", ", ""); + fprintf(file, ");"); +} + +void IfInputAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + ok &= m_pParameters->Compile(); + + if (m_pSignal->GetParameters()->GetCount() == m_pParameters->GetCount()) + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pSignal->GetParameters()->GetAt(i); + ok &= m_pParameters->GetAt(i)->Match(type); + ok &= m_pParameters->GetAt(i)->IsReference(); + ok &= !m_pParameters->GetAt(i)->IsTimed(); + } + else + ok = 0; + + SetFlag(CORRECT, ok); +} + +void IfInputAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file,"input,%s,(",m_pSignal->GetName()); + for(int i = 0, on = 0; i < m_pParameters->GetCount(); i++) { + IfExpression* par = m_pParameters->GetAt(i); + IfType* type = m_pSignal->GetParameters()->GetAt(i); + if (!par->IsVoid()) { + if (on) fprintf(file, ","); + par->Code(file); + fprintf(file, ",p%d,%s", i+1, type->GetName()); + on = 1; + } + } + fprintf(file,"))"); +} + +int IfInputAction::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) + use |= m_pParameters->GetAt(i)->Use(Variable) && + !m_pParameters->GetAt(i)->IsVariable(); + return use; +} + +int IfInputAction::Def(const IfVariable* Variable) const { + int def = 0; + for(int i = 0; i < m_pParameters->GetCount() && !def; i++) + def |= m_pParameters->GetAt(i)->Def(Variable); + return def; +} + +/* + * + * output action + * + */ + +IfOutputAction::IfOutputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* Via, + IfExpression* To, + unsigned Flags) + : IfAction(Flags) { + m_pSignal = Signal; + m_pParameters = Parameters; + m_pVia = Via; + m_pTo = To; +} + +IfOutputAction::~IfOutputAction() { + delete m_pParameters; + if (m_pVia) delete m_pVia; + if (m_pTo) delete m_pTo; +} + +void IfOutputAction::Dump(FILE* file) const { + fprintf(file, "output %s(", m_pSignal->GetName()); + m_pParameters->Dump(file, "", ", ", ""); + fprintf(file, ")"); + if (m_pVia) { + fprintf(file, " via "); + m_pVia->Dump(file); + } + if (m_pTo) { + fprintf(file, " to "); + m_pTo->Dump(file); + } + fprintf(file, ";"); +} + +void IfOutputAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + ok &= m_pParameters->Compile(); + + if (m_pSignal->GetParameters()->GetCount() == m_pParameters->GetCount()) + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pSignal->GetParameters()->GetAt(i); + ok &= m_pParameters->GetAt(i)->Match(type); + ok &= !m_pParameters->GetAt(i)->IsTimed(); + } + else + ok = 0; + + if (m_pVia) { + ok &= m_pVia->Compile(); + ok &= m_pVia->Match(TYPES[IfBasicType::PID]); + ok &= !m_pVia->IsTimed(); + } + + if (m_pTo) { + ok &= m_pTo->Compile(); + ok &= m_pTo->Match(TYPES[IfBasicType::PID]); + ok &= !m_pTo->IsTimed(); + } + + if ( ((IfEntity*)CONTEXT.GetAt(1))->IsObserver() && ((IfObserverEntity*)(CONTEXT.GetAt(1)))->getKind() < IfObserverEntity::INTRUSIVE ) { + Protest("intrusive statement in non-intrusive observer"); + ok = 0; + } + + SetFlag(CORRECT, ok); +} + +void IfOutputAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "output,%s,(", m_pSignal->GetName()); + m_pParameters->Code(file,"",",",""); + fprintf(file,"),"); + if (m_pVia) m_pVia->Code(file); else fprintf(file, "0"); + fprintf(file, ","); + if (m_pTo) m_pTo->Code(file); else fprintf(file,"0"); + fprintf(file,")"); +} + +int IfOutputAction::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) + use |= m_pParameters->GetAt(i)->Use(Variable); + if (m_pVia) use |= m_pVia->Use(Variable); + if (m_pTo) use |= m_pTo->Use(Variable); + return use; +} + +int IfOutputAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * acquire action + * + */ + +IfAcquireAction::IfAcquireAction(IfList<IfResource>* Resources, + unsigned Flags) + : IfAction(Flags) { + m_pResources = Resources; +} + +IfAcquireAction::~IfAcquireAction() { + delete m_pResources; +} + +void IfAcquireAction::Dump(FILE* file) const { + fprintf(file, "acquire "); + m_pResources->DumpName(file, "", ", ", ""); + fprintf(file, ";"); +} + +void IfAcquireAction::PreCompile() { + IfAction::PreCompile(); +} + +void IfAcquireAction::Code(FILE* file) const { + IfAction::Code(file); + m_pResources->DumpName(file, "acquire,", ",", ")"); +} + +int IfAcquireAction::Use(const IfVariable* Variable) const { + return 0; +} + +int IfAcquireAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * release action + * + */ + +IfReleaseAction::IfReleaseAction(IfList<IfResource>* Resources, + unsigned Flags) + : IfAction(Flags) { + m_pResources = Resources; +} + +IfReleaseAction::~IfReleaseAction() { + delete m_pResources; +} + +void IfReleaseAction::Dump(FILE* file) const { + fprintf(file, "release "); + m_pResources->DumpName(file, "", ", ", ""); + fprintf(file, ";"); +} + +void IfReleaseAction::PreCompile() { + IfAction::PreCompile(); +} + +void IfReleaseAction::Code(FILE* file) const { + IfAction::Code(file); + m_pResources->DumpName(file, "release,", ",", ")"); +} + +int IfReleaseAction::Use(const IfVariable* Variable) const { + return 0; +} + +int IfReleaseAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * fork action + * + */ + +IfForkAction::IfForkAction(IfExpression* Lhs, + char* Name, + IfList<IfExpression>* Parameters, + unsigned Flags) + :IfAction(Flags) { + m_pLhs = Lhs; + m_pProcess = NULL; + m_pSignalroute = NULL; + m_pName = Name; + m_pParameters = Parameters; +} + +IfForkAction::~IfForkAction() { + if (m_pLhs) delete m_pLhs; + free(m_pName); + delete m_pParameters; +} + +void IfForkAction::Dump(FILE* file) const { + if (m_pLhs) { + m_pLhs->Dump(file); + fprintf(file, " := "); + } + fprintf(file, "fork %s(", m_pName); + m_pParameters->Dump(file, "", ", ", ""); + fprintf(file, ");"); +} + +void IfForkAction::PreCompile() { + IfAction::PreCompile(); + + IfSystemEntity* sys = (IfSystemEntity*) CONTEXT[0]; + int ok = 1; + + if (m_pLhs) { + ok &= m_pLhs->Compile(); + ok &= m_pLhs->IsReference(); + ok &= m_pLhs->Match(TYPES[IfBasicType::PID]); + ok &= !m_pLhs->IsTimed(); + } + + ok &= m_pParameters->Compile(); + for(int i = 0; i < m_pParameters->GetCount(); i++) + ok &= !m_pParameters->GetAt(i)->IsTimed(); + + m_pProcess = sys->GetProcesses()->Find(m_pName); + m_pSignalroute = sys->GetSignalroutes()->Find(m_pName); + + ok &= m_pProcess || m_pSignalroute; + + if (m_pProcess) { + if (m_pProcess->GetParameters()->GetCount() == m_pParameters->GetCount()) + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pProcess->GetParameters()->GetAt(i)->GetType(); + ok &= m_pParameters->GetAt(i)->Match(type); + } + else + ok = 0; + } + + if (m_pSignalroute) + ok &= m_pParameters->GetCount() == 0 + && m_pSignalroute->GetFrom() != NULL + && m_pSignalroute->GetTo() != NULL; + + if ( ((IfEntity*)CONTEXT.GetAt(1))->IsObserver() && ((IfObserverEntity*)(CONTEXT.GetAt(1)))->getKind() < IfObserverEntity::INTRUSIVE ) { + Protest("intrusive statement in non-intrusive observer"); + ok = 0; + } + + SetFlag(CORRECT, ok); +} + +void IfForkAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "fork,%s,%s,(", + m_pProcess ? "instance" : "buffer", m_pName); + m_pParameters->Code(file,"",",",""); + fprintf(file, "),"); + if (m_pLhs) + m_pLhs->Code(file); + fprintf(file, ")"); +} + +int IfForkAction::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) + use |= m_pParameters->GetAt(i)->Use(Variable); + if (m_pLhs) + use |= m_pLhs->Use(Variable) && !m_pLhs->IsVariable(); + return use; +} + +int IfForkAction::Def(const IfVariable* Variable) const { + int def = 0; + if (m_pLhs) + def |= m_pLhs->Def(Variable); + return def; +} + +/* + * + * kill action + * + */ + +IfKillAction::IfKillAction(IfExpression* Rhs, + unsigned Flags) + : IfAction(Flags) { + m_pRhs = Rhs; +} + +IfKillAction::~IfKillAction() { + delete m_pRhs; +} + +void IfKillAction::Dump(FILE* file) const { + fprintf(file, "kill "); + m_pRhs->Dump(file); + fprintf(file, ";"); +} + +void IfKillAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + ok &= m_pRhs->Compile(); + ok &= m_pRhs->Match(TYPES[IfBasicType::PID]); + ok &= !m_pRhs->IsTimed(); + + if ( ((IfEntity*)CONTEXT.GetAt(1))->IsObserver() && ((IfObserverEntity*)(CONTEXT.GetAt(1)))->getKind() < IfObserverEntity::INTRUSIVE ) { + Protest("intrusive statement in non-intrusive observer"); + ok = 0; + } + + SetFlag(CORRECT, ok); +} + +void IfKillAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file,"kill,"); + m_pRhs->Code(file); + fprintf(file, ")"); +} + +int IfKillAction::Use(const IfVariable* Variable) const { + return m_pRhs->Use(Variable); +} + +int IfKillAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * call action + * + */ + +IfCallAction::IfCallAction(IfExpression* Lhs, + IfProcedure* Procedure, + IfList<IfExpression>* Parameters, + unsigned Flags) + : IfAction(Flags) { + m_pLhs = Lhs; + m_pProcedure = Procedure; + m_pParameters = Parameters; +} + +IfCallAction::~IfCallAction() { + if (m_pLhs) delete m_pLhs; + delete m_pParameters; +} + +void IfCallAction::Dump(FILE* file) const { + if (m_pLhs) { + m_pLhs->Dump(file); + fprintf(file, " := "); + } + fprintf(file, "call %s(", m_pProcedure->GetName()); + m_pParameters->Dump(file, "", ",", ""); + fprintf(file, ");"); +} + +void IfCallAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + if (m_pLhs) { + ok &= m_pLhs->Compile(); + ok &= m_pLhs->IsReference(); + ok &= m_pProcedure->GetReturn() && + m_pLhs->Match(m_pProcedure->GetReturn()); + ok &= !m_pLhs->IsTimed(); + } + + ok &= m_pParameters->Compile(); + if (m_pParameters->GetCount() == m_pProcedure->GetParameters()->GetCount()) + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfVariable* variable = m_pProcedure->GetParameters()->GetAt(i); + ok &= m_pParameters->GetAt(i)->Match(variable->GetType()); + if (variable->IsInout() || variable->IsOut()) + ok &= m_pParameters->GetAt(i)->IsReference(); + ok &= !m_pParameters->GetAt(i)->IsTimed(); + } + else + ok = 0; + + SetFlag(CORRECT,ok); + +} + +void IfCallAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file,"call,%s,(", m_pProcedure->GetName()); + m_pParameters->Code(file, "", ",", ""); + fprintf(file, "),"); + if (m_pLhs) + m_pLhs->Code(file); + fprintf(file, ")"); +} + +int IfCallAction::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) { + IfVariable* par_i = m_pProcedure->GetParameters()->GetAt(i); + IfExpression* arg_i = m_pParameters->GetAt(i); + if (par_i->IsIn() || par_i->IsInout()) + use |= arg_i->Use(Variable); + if (par_i->IsOut()) + use |= arg_i->Use(Variable) && !arg_i->IsVariable(); + } + if (m_pLhs) + use |= m_pLhs->Use(Variable) && !m_pLhs->IsVariable(); + return use; +} + +int IfCallAction::Def(const IfVariable* Variable) const { + int def = 0; + for(int i = 0; i < m_pParameters->GetCount() && !def; i++) { + IfVariable* par_i = m_pProcedure->GetParameters()->GetAt(i); + IfExpression* arg_i = m_pParameters->GetAt(i); + if (par_i->IsOut() || par_i->IsInout()) + def |= arg_i->Def(Variable); + } + if (m_pLhs) + def |= m_pLhs->Def(Variable); + return def; +} + +/* + * + * nextstate action + * + */ + +IfNextstateAction::IfNextstateAction(IfState* State, + unsigned Flags) + : IfAction(Flags) { + m_pState = State; + m_pStateName = NULL; +} + +IfNextstateAction::IfNextstateAction(char* StateName, + unsigned Flags) + : IfAction(Flags) { + m_pState = NULL; + m_pStateName = StateName; +} + +IfNextstateAction::~IfNextstateAction() { + if (m_pStateName) free(m_pStateName); +} + +void IfNextstateAction::Dump(FILE* file) const { + fprintf(file, "nextstate %s;", + m_pState ? m_pState->GetName() : m_pStateName); +} + +void IfNextstateAction::PreCompile() { + + IfAction::PreCompile(); + + if (strcmp(m_pStateName, "-") == 0) { + SetFlag(CORRECT, 1); + return; + } + + int ok = 1; + + /* + * + * state name ~ literal_1 @ literal_2 @ ... @ literal_n + * + * implemented too early ;-) + + IfState* base[3] = {NULL, NULL, NULL}; + + base[0] = (IfState*) CONTEXT.Top(-3); + base[1] = ((IfProcessEntity*) CONTEXT[1])->GetEntry(); + if (base[0] == base[1]) base[1] = NULL; + + for(int i = 0; base[i]; i++) { + + IfState* current = base[i]; + for(int k = 0, j;; ) { + + char literal[256] = ""; + for(j = 0; m_pStateName[k] != '\0' && + m_pStateName[k] != '@'; j++, k++) + literal[j] = m_pStateName[k]; + literal[j] = '\0'; + + if (m_pStateName[k] == '@') + k++; + + current = current->GetStates()->Find(literal); + if (current == NULL) + break; + + if (m_pStateName[k] == '\0') { + m_pState = current; + break; + } + } + + if (m_pState) + break; + } + + * + * + */ + + IfState* top = ((IfProcessEntity*) CONTEXT[1])->GetEntry(); + + m_pState = top->Find(m_pStateName); + + ok &= m_pState != NULL; + + SetFlag(CORRECT, ok); +} + +void IfNextstateAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "nextstate,("); + if (m_pState != NULL) { + IfState* lca = IfState::LeastCommonAncestor(TRANSITION->GetSource(), m_pState); + lca->CodeExit(file); + m_pState->CodeEntry(file); + } + fprintf(file, "))"); +} + +int IfNextstateAction::Use(const IfVariable* Variable) const { + return 0; +} + +int IfNextstateAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * stop action + * + */ + +IfStopAction::IfStopAction(unsigned Flags) + : IfAction(Flags) { +} + +void IfStopAction::Dump(FILE* file) const { + fprintf(file, "stop;"); +} + +void IfStopAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "stop)"); +} + +int IfStopAction::Use(const IfVariable* Variable) const { + return 0; +} + +int IfStopAction::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * flush action + * + */ + +IfFlushAction::IfFlushAction(unsigned Flags) +: IfAction(Flags) { +} + +void IfFlushAction::Dump(FILE* file) const { + fprintf(file, "flush;"); +} + +void IfFlushAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + if (CONTEXT.GetSize() < 2 || + (CONTEXT.GetSize() >= 2 && !((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver())) { + Protest("statement only valid in observers"); + ok = 0; + } + + SetFlag(CORRECT, ok); +} + +void IfFlushAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "flush)"); +} + +/* + * + * cut action + * + */ + +IfCutAction::IfCutAction(unsigned Flags) +: IfAction(Flags) { +} + +void IfCutAction::Dump(FILE* file) const { + fprintf(file, "cut;"); +} + +void IfCutAction::PreCompile() { + IfAction::PreCompile(); + + int ok = 1; + + if (CONTEXT.GetSize() < 2 || + (CONTEXT.GetSize() >= 2 && !((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver())) { + Protest("statement only valid in observers"); + ok = 0; + } + + if ( ((IfEntity*)CONTEXT.GetAt(1))->IsObserver() && ((IfObserverEntity*)(CONTEXT.GetAt(1)))->getKind() < IfObserverEntity::CUT ) { + Protest("cut statement in pure observer"); + ok = 0; + } + + SetFlag(CORRECT, ok); +} + +void IfCutAction::Code(FILE* file) const { + IfAction::Code(file); + fprintf(file, "cut)"); +} + + + + + + +/* + * + * Match Actions + * + */ + +/* + * + * match input action + * + */ + +IfMatchInputAction::IfMatchInputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* sigvar, + IfExpression* in, + unsigned isDiscard, + unsigned Flags) + : IfMatchAction(Flags) { + m_pSignal = Signal; + m_pParameters = Parameters; + m_pSigvar = sigvar; + m_pIn = in; + m_nIsDiscard = isDiscard; +} + +IfMatchInputAction::~IfMatchInputAction() { + if(m_pParameters) delete m_pParameters; + if(m_pSigvar) delete m_pSigvar; + if(m_pIn) delete m_pIn; +} + +void IfMatchInputAction::Dump(FILE* file) const { + if(m_nIsDiscard) + fprintf(file, "match discard "); + else + fprintf(file, "match input "); + if(m_pSignal != NULL) { + fprintf(file, "%s(", m_pSignal->GetName()); + m_pParameters->Dump(file, "", ", ", ""); + fprintf(file, ")"); + } else if(m_pSigvar != NULL) { + m_pSigvar->Dump(file); + } + if(m_pIn) { + fprintf(file, " in "); + m_pIn->Dump(file); + } + fprintf(file, ";"); +} + +void IfMatchInputAction::PreCompile() { + IfMatchAction::PreCompile(); + + int ok = 1; + + if(m_pSignal != NULL) { + m_pSignal->SetFlag(IfSignal::OBSERVED, true); + ok &= m_pParameters->Compile(); + if (m_pSignal->GetParameters()->GetCount() == m_pParameters->GetCount()) + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pSignal->GetParameters()->GetAt(i); + ok &= m_pParameters->GetAt(i)->Match(type); + ok &= m_pParameters->GetAt(i)->IsReference(); + ok &= !m_pParameters->GetAt(i)->IsTimed(); + } + else + ok = 0; + } else if(m_pSigvar != NULL) { + ok &= m_pSigvar->Compile(); + ok &= m_pSigvar->Match( ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal") ); + ok &= m_pSigvar->IsReference(); + } + if(m_pIn) { + ok &= m_pIn->Compile(); + ok &= m_pIn->Match(TYPES[IfBasicType::PID]); + ok &= m_pIn->IsReference(); + } + + SetFlag(CORRECT, ok); +} + +IfExpression* IfMatchInputAction::GetObsGuard() const { + IfEventObsExpression* tmp; + IfInstanceofExpression* res; + if(m_pSignal != NULL) { + tmp = new IfEventObsExpression((m_nIsDiscard?IfEventObsExpression::DISCARD : IfEventObsExpression::INPUT), m_pSignal->GetName(), NULL/*m_pIn*/); + if(!tmp->Compile()) return NULL; + res = new IfInstanceofExpression(tmp, m_pSignal->GetName()); + } else { + tmp = new IfEventObsExpression((m_nIsDiscard?IfEventObsExpression::DISCARD : IfEventObsExpression::INPUT), /*m_pSignal->GetName()*/NULL, NULL/*m_pIn*/); + if(!tmp->Compile()) return NULL; + res = new IfInstanceofExpression(tmp, NULL); + } + if(!res->Compile()) return NULL; + return res; +} + +void IfMatchInputAction::Code(FILE* file) const { + IfMatchAction::Code(file); + if(m_pSignal) { + if(m_nIsDiscard) fprintf(file,"matchdiscard,%s,(", m_pSignal->GetName() ); + else fprintf(file,"matchinput,%s,(", m_pSignal->GetName() ); + for(int i = 0, on = 0; i < m_pParameters->GetCount(); i++) { + IfExpression* par = m_pParameters->GetAt(i); + IfType* type = m_pSignal->GetParameters()->GetAt(i); + if (!par->IsVoid()) { + if (on) fprintf(file, ","); + par->Code(file); + fprintf(file, ",p%d,%s", i+1, type->GetName()); + on = 1; + } + } + fprintf(file,"),"); + } else { + if(m_nIsDiscard) fprintf(file,"matchdiscard,,(),"); + else fprintf(file,"matchinput,,(),"); + } + if(m_pSigvar) m_pSigvar->Code(file); + fprintf(file,","); + if(m_pIn) { + fprintf(file,"&"); + m_pIn->Code(file); + } else fprintf(file,"NULL"); + fprintf(file,")"); +} + +int IfMatchInputAction::Use(const IfVariable* Variable) const { + //TODO!!! + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) + use |= m_pParameters->GetAt(i)->Use(Variable) && + !m_pParameters->GetAt(i)->IsVariable(); + return use; +} + +int IfMatchInputAction::Def(const IfVariable* Variable) const { + //TODO!!! + int def = 0; + for(int i = 0; i < m_pParameters->GetCount() && !def; i++) + def |= m_pParameters->GetAt(i)->Def(Variable); + return def; +} + +/* + * + * match output action + * + */ + +IfMatchOutputAction::IfMatchOutputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* sigvar, + IfExpression* ord, + IfExpression* from, + IfExpression* via, + IfExpression* to, + unsigned Flags) + : IfMatchAction(Flags) { + m_pSignal = Signal; + m_pParameters = Parameters; + m_pSigvar = sigvar; + m_pOrd = ord; + m_pFrom = from; + m_pVia = via; + m_pTo = to; +} + +IfMatchOutputAction::~IfMatchOutputAction() { + if(m_pParameters) delete m_pParameters; + if(m_pSigvar) delete m_pSigvar; + if(m_pOrd) delete m_pOrd; + if(m_pFrom) delete m_pFrom; + if(m_pVia) delete m_pVia; + if(m_pTo) delete m_pTo; +} + +void IfMatchOutputAction::Dump(FILE* file) const { + fprintf(file, "match output "); + if(m_pSignal != NULL) { + fprintf(file, "%s(", m_pSignal->GetName()); + m_pParameters->Dump(file, "", ", ", ""); + fprintf(file, ")"); + } else if(m_pSigvar != NULL) { + m_pSigvar->Dump(file); + } + + if(m_pOrd) { + fprintf(file, "[ "); + m_pOrd->Dump(file); + fprintf(file, " ]"); + } + if(m_pFrom) { + fprintf(file, " from "); + m_pFrom->Dump(file); + } + if(m_pVia) { + fprintf(file, " via "); + m_pVia->Dump(file); + } + if(m_pTo) { + fprintf(file, " to "); + m_pTo->Dump(file); + } + fprintf(file, ";"); +} + +void IfMatchOutputAction::PreCompile() { + IfMatchAction::PreCompile(); + + int ok = 1; + + if(m_pSignal != NULL) { + m_pSignal->SetFlag(IfSignal::OBSERVED, true); + ok &= m_pParameters->Compile(); + if (m_pSignal->GetParameters()->GetCount() == m_pParameters->GetCount()) + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pSignal->GetParameters()->GetAt(i); + ok &= m_pParameters->GetAt(i)->Match(type); + ok &= m_pParameters->GetAt(i)->IsReference(); + ok &= !m_pParameters->GetAt(i)->IsTimed(); + } + else + ok = 0; + } else if(m_pSigvar != NULL) { + ok &= m_pSigvar->Compile(); + ok &= m_pSigvar->Match( ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal") ); + ok &= m_pSigvar->IsReference(); + } + + ok &= m_pOrd ? m_pOrd->Compile() : 1; + ok &= m_pOrd ? m_pOrd->Match(TYPES[IfBasicType::INTEGER]) : 1; + + ok &= m_pFrom ? m_pFrom->Compile() : 1; + ok &= m_pFrom ? m_pFrom->Match(TYPES[IfBasicType::PID]) : 1; + ok &= m_pFrom ? m_pFrom->IsReference() : 1; + + ok &= m_pVia ? m_pVia->Compile() : 1; + ok &= m_pVia ? m_pVia->Match(TYPES[IfBasicType::PID]) : 1; + ok &= m_pVia ? m_pVia->IsReference() : 1; + + ok &= m_pTo ? m_pTo->Compile() : 1; + ok &= m_pTo ? m_pTo->Match(TYPES[IfBasicType::PID]) : 1; + ok &= m_pTo ? m_pTo->IsReference() : 1; + + SetFlag(CORRECT, ok); +} + +IfExpression* IfMatchOutputAction::GetObsGuard() const { + IfEventObsExpression* tmp; + IfInstanceofExpression* res; + if(m_pSignal != NULL) { + tmp = new IfEventObsExpression(IfEventObsExpression::OUTPUT, m_pSignal->GetName(), m_pOrd, /*m_pFrom*/NULL, /*m_pVia*/NULL, /*m_pTo*/NULL); + if(!tmp->Compile()) return NULL; + res = new IfInstanceofExpression(tmp, m_pSignal->GetName()); + } else { + tmp = new IfEventObsExpression(IfEventObsExpression::OUTPUT, /*m_pSignal->GetName()*/NULL, m_pOrd, /*m_pFrom*/NULL, /*m_pVia*/NULL, /*m_pTo*/NULL); + if(!tmp->Compile()) return NULL; + res = new IfInstanceofExpression(tmp, NULL); + } + if(!res->Compile()) return NULL; + return res; +} + +void IfMatchOutputAction::Code(FILE* file) const { + IfMatchAction::Code(file); + if(m_pSignal) { + fprintf(file,"matchoutput,%s,(",m_pSignal->GetName()); + for(int i = 0, on = 0; i < m_pParameters->GetCount(); i++) { + IfExpression* par = m_pParameters->GetAt(i); + IfType* type = m_pSignal->GetParameters()->GetAt(i); + if (!par->IsVoid()) { + if (on) fprintf(file, ","); + par->Code(file); + fprintf(file, ",p%d,%s", i+1, type->GetName()); + on = 1; + } + } + fprintf(file,"),"); + } else + fprintf(file,"matchoutput,,(),"); + if(m_pOrd) m_pOrd->Code(file); + else fprintf(file,"0"); + fprintf(file,","); + + if(m_pSigvar) m_pSigvar->Code(file); + fprintf(file,","); + + if(m_pFrom) { fprintf(file,"&"); m_pFrom->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,","); + + if(m_pVia) { fprintf(file,"&"); m_pVia->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,","); + + if(m_pTo) { fprintf(file,"&"); m_pTo->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,")"); +} + +int IfMatchOutputAction::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) + use |= m_pParameters->GetAt(i)->Use(Variable) && + !m_pParameters->GetAt(i)->IsVariable(); + return use; +} + +int IfMatchOutputAction::Def(const IfVariable* Variable) const { + int def = 0; + for(int i = 0; i < m_pParameters->GetCount() && !def; i++) + def |= m_pParameters->GetAt(i)->Def(Variable); + return def; +} + +/* + * + * match fork action + * + */ + +IfMatchForkAction::IfMatchForkAction(char* name, + IfExpression* var, + IfExpression* in, + unsigned Flags) + : IfMatchAction(Flags) { + m_pName = name; + m_pIn = in; + m_pVar = var; + m_pProcess = NULL; +} + +IfMatchForkAction::~IfMatchForkAction() { + delete m_pVar; +} + +void IfMatchForkAction::Dump(FILE* file) const { + fprintf(file, "match fork ( "); + if( m_pVar ) m_pVar->Dump(file); + fprintf(file, ") "); + if( m_pName ) fprintf(file, " %s ", m_pProcess ? m_pProcess->GetName() : m_pName); + if(m_pIn) { + fprintf(file, " in "); + m_pIn->Dump(file); + } + fprintf(file, ";"); +} + +void IfMatchForkAction::PreCompile() { + IfMatchAction::PreCompile(); + + int ok = 1; + + if( m_pName ) { + m_pProcess = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetProcesses()->Find(m_pName); + if( !m_pProcess ) ok = 0; + } + if( m_pVar ) { + m_pVar->Compile(); + ok &= m_pVar->Match(TYPES[IfBasicType::PID]); + ok &= m_pVar->IsReference(); + ok &= !m_pVar->IsTimed(); + } + + ok &= m_pIn ? m_pIn->Compile() : 1; + ok &= m_pIn ? m_pIn->Match(TYPES[IfBasicType::PID]) : 1; + ok &= m_pIn ? m_pIn->IsReference() : 1; + + SetFlag(CORRECT, ok); +} + +IfExpression* IfMatchForkAction::GetObsGuard() const { + IfEventObsExpression* tmp = new IfEventObsExpression(IfEventObsExpression::FORK, m_pProcess ? m_pProcess->GetName() : m_pName, /*m_pIn*/NULL); + if(!tmp->Compile()) return NULL; + return tmp; +} + +void IfMatchForkAction::Code(FILE* file) const { + IfMatchAction::Code(file); + fprintf(file,"matchfork,%s,",m_pProcess ? m_pProcess->GetName() : ""); + if(m_pVar) { fprintf(file,"&"); m_pVar->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,","); + if(m_pIn) { fprintf(file,"&"); m_pIn->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,")"); +} + +/* + * + * match kill action + * + */ + +IfMatchKillAction::IfMatchKillAction(char* name, + IfExpression* var, + IfExpression* in, + unsigned Flags) + : IfMatchAction(Flags) { + m_pName = name; + m_pIn = in; + m_pVar = var; + m_pProcess = NULL; +} + +IfMatchKillAction::~IfMatchKillAction() { + delete m_pVar; +} + +void IfMatchKillAction::Dump(FILE* file) const { + fprintf(file, "match kill ( "); + if( m_pVar ) m_pVar->Dump(file); + fprintf(file, ") "); + if( m_pName ) fprintf(file, " \"%s\" ", m_pProcess ? m_pProcess->GetName() : m_pName); + if(m_pIn) { + fprintf(file, " in "); + m_pIn->Dump(file); + } + fprintf(file, ";"); +} + +void IfMatchKillAction::PreCompile() { + IfMatchAction::PreCompile(); + + int ok = 1; + + if( m_pName ) { + m_pProcess = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetProcesses()->Find(m_pName); + if( !m_pProcess ) ok = 0; + } + + if( m_pVar ) { + m_pVar->Compile(); + ok &= m_pVar->Match(TYPES[IfBasicType::PID]); + ok &= m_pVar->IsReference(); + } + + ok &= m_pIn ? m_pIn->Compile() : 1; + ok &= m_pIn ? m_pIn->Match(TYPES[IfBasicType::PID]) : 1; + ok &= m_pIn ? m_pIn->IsReference() : 1; + + SetFlag(CORRECT, ok); +} + +IfExpression* IfMatchKillAction::GetObsGuard() const { + IfEventObsExpression* tmp = new IfEventObsExpression(IfEventObsExpression::KILL, m_pProcess ? m_pProcess->GetName() : m_pName, /*m_pPid*/NULL, /*m_pIn*/NULL); + if(!tmp->Compile()) return NULL; + return tmp; +} + +void IfMatchKillAction::Code(FILE* file) const { + IfMatchAction::Code(file); + fprintf(file,"matchkill,%s,", m_pProcess ? m_pProcess->GetName() : ""); + if(m_pVar) { fprintf(file,"&"); m_pVar->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,","); + if(m_pIn) { fprintf(file, "&"); m_pIn->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,")"); +} + +/* + * + * match deliver action + * + */ + +IfMatchDeliverAction::IfMatchDeliverAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* sigvar, + IfExpression* from, + unsigned Flags) + : IfMatchAction(Flags) { + m_pSignal = Signal; + m_pParameters = Parameters; + m_pSigvar = sigvar; + m_pFrom = from; +} + +IfMatchDeliverAction::~IfMatchDeliverAction() { + if(m_pParameters) delete m_pParameters; + if(m_pFrom) delete m_pFrom; + if(m_pSigvar) delete m_pSigvar; +} + +void IfMatchDeliverAction::Dump(FILE* file) const { + fprintf(file, "match deliver "); + if(m_pSignal != NULL) { + fprintf(file, "%s(", m_pSignal->GetName()); + m_pParameters->Dump(file, "", ", ", ""); + fprintf(file, ")"); + } else if(m_pSigvar != NULL) { + m_pSigvar->Dump(file); + } + if(m_pFrom) { + fprintf(file, " from "); + m_pFrom->Dump(file); + } + fprintf(file, ";"); +} + +void IfMatchDeliverAction::PreCompile() { + IfMatchAction::PreCompile(); + + int ok = 1; + + if(m_pSignal != NULL) { + ok &= m_pParameters->Compile(); + if (m_pSignal->GetParameters()->GetCount() == m_pParameters->GetCount()) + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pSignal->GetParameters()->GetAt(i); + ok &= m_pParameters->GetAt(i)->Match(type); + ok &= m_pParameters->GetAt(i)->IsReference(); + ok &= !m_pParameters->GetAt(i)->IsTimed(); + } + else + ok = 0; + } else if(m_pSigvar != NULL) { + ok &= m_pSigvar->Compile(); + ok &= m_pSigvar->Match( ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal") ); + ok &= m_pSigvar->IsReference(); + } + ok &= m_pFrom ? m_pFrom->Compile() : 1; + ok &= m_pFrom ? m_pFrom->Match(TYPES[IfBasicType::PID]) : 1; + ok &= m_pFrom ? m_pFrom->IsReference() : 1; + + SetFlag(CORRECT, ok); +} + +IfExpression* IfMatchDeliverAction::GetObsGuard() const { + IfEventObsExpression* tmp; + IfInstanceofExpression* res; + if(m_pSignal != NULL) { + tmp = new IfEventObsExpression(IfEventObsExpression::DELIVER, m_pSignal->GetName(), /*m_pFrom*/NULL); + if(!tmp->Compile()) return NULL; + res = new IfInstanceofExpression(tmp, m_pSignal->GetName()); + } else { + tmp = new IfEventObsExpression(IfEventObsExpression::DELIVER, /*m_pSignal->GetName()*/NULL, /*m_pFrom*/NULL); + if(!tmp->Compile()) return NULL; + res = new IfInstanceofExpression(tmp, NULL); + } + if(!res->Compile()) return NULL; + return res; +} + +void IfMatchDeliverAction::Code(FILE* file) const { + IfMatchAction::Code(file); + if(m_pSignal) { + fprintf(file,"matchdeliver,%s,(", m_pSignal->GetName()); + for(int i = 0, on = 0; i < m_pParameters->GetCount(); i++) { + IfExpression* par = m_pParameters->GetAt(i); + IfType* type = m_pSignal->GetParameters()->GetAt(i); + if (!par->IsVoid()) { + if (on) fprintf(file, ","); + par->Code(file); + fprintf(file, ",p%d,%s", i+1, type->GetName()); + on = 1; + } + } + fprintf(file,"),"); + } else + fprintf(file,"matchdeliver,,(),"); + if(m_pSigvar) m_pSigvar->Code(file); + fprintf(file,","); + if(m_pFrom) { fprintf(file,"&"); m_pFrom->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,")"); +} + +int IfMatchDeliverAction::Use(const IfVariable* Variable) const { + // TODO!!! + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) + use |= m_pParameters->GetAt(i)->Use(Variable) && + !m_pParameters->GetAt(i)->IsVariable(); + return use; +} + +int IfMatchDeliverAction::Def(const IfVariable* Variable) const { + // TODO!!! + int def = 0; + for(int i = 0; i < m_pParameters->GetCount() && !def; i++) + def |= m_pParameters->GetAt(i)->Def(Variable); + return def; +} + +/* + * + * match informal action + * + */ + +IfMatchInformalAction::IfMatchInformalAction(char* name, + IfExpression* in, + unsigned Flags) + : IfMatchAction(Flags) { + m_pName = name; + m_pIn = in; +} + +IfMatchInformalAction::~IfMatchInformalAction() { +} + +void IfMatchInformalAction::Dump(FILE* file) const { + fprintf(file, "match informal %s ", m_pName); + if(m_pIn) { + fprintf(file, "in "); + m_pIn->Dump(file); + } + fprintf(file, ";"); +} + +void IfMatchInformalAction::PreCompile() { + IfMatchAction::PreCompile(); + + int ok = 1; + + ok &= m_pIn ? m_pIn->Compile() : 1; + ok &= m_pIn ? m_pIn->Match(TYPES[IfBasicType::PID]) : 1; + ok &= m_pIn ? m_pIn->IsReference() : 1; + + SetFlag(CORRECT, 1); +} + +IfExpression* IfMatchInformalAction::GetObsGuard() const { + IfEventObsExpression* tmp = new IfEventObsExpression(IfEventObsExpression::INFORMAL, m_pName, NULL/*m_pIn*/); + if(!tmp->Compile()) return NULL; + return tmp; +} + +void IfMatchInformalAction::Code(FILE* file) const { + IfMatchAction::Code(file); + fprintf(file,"matchinformal,%s,",m_pName); + if(m_pIn) { fprintf(file,"&"); m_pIn->Code(file); } + else fprintf(file,"NULL"); + fprintf(file,")"); +} + +/* + * + * match probability action + * + */ + +IfMatchProbabilityAction::IfMatchProbabilityAction(IfExpression* var, + unsigned Flags) + : IfMatchAction(Flags) { + m_pVar = var; +} + +IfMatchProbabilityAction::~IfMatchProbabilityAction() { + delete m_pVar; +} + +void IfMatchProbabilityAction::Dump(FILE* file) const { + fprintf(file, "match probability ( "); + if( m_pVar ) m_pVar->Dump(file); + fprintf(file, ") "); + fprintf(file, ";"); +} + +void IfMatchProbabilityAction::PreCompile() { + IfMatchAction::PreCompile(); + + int ok = 1; + + if( m_pVar ) { + m_pVar->Compile(); + ok &= m_pVar->Match(TYPES[IfBasicType::REAL]); + ok &= m_pVar->IsReference(); + ok &= !m_pVar->IsTimed(); + } + + SetFlag(CORRECT, ok); +} + +IfExpression* IfMatchProbabilityAction::GetObsGuard() const { + IfEventObsExpression* tmp = new IfEventObsExpression(IfEventObsExpression::PROBABILITY); + if(!tmp->Compile()) return NULL; + return tmp; +} + +void IfMatchProbabilityAction::Code(FILE* file) const { + IfMatchAction::Code(file); + fprintf(file,"matchprobability,"); + if(m_pVar) m_pVar->Code(file); + fprintf(file,")"); +} + diff --git a/src/model/action.h b/src/model/action.h new file mode 100644 index 0000000000000000000000000000000000000000..8b87da983c5e480cf3a511d0c891b4b60df55ae0 --- /dev/null +++ b/src/model/action.h @@ -0,0 +1,862 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract action interface + * + */ + +class IfAction : public IfObject { + + public: + IfAction(unsigned Flags = 0); + virtual ~IfAction() {} + + public: + virtual const char* GetClass() const + { return "action"; } + virtual int IsAction() const + { return 1; } + + virtual void PreCompile(); + virtual void Code(FILE* file) const; + void Alpha(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + public: + virtual int IsSkip() const { return 0; } + virtual int IsInformal() const { return 0; } + virtual int IsTask() const { return 0; } + virtual int IsSet() const { return 0; } + virtual int IsReset() const { return 0; } + virtual int IsInput() const { return 0; } + virtual int IsOutput() const { return 0; } + virtual int IsAcquire() const { return 0; } + virtual int IsRelease() const { return 0; } + virtual int IsFork() const { return 0; } + virtual int IsKill() const { return 0; } + virtual int IsCall() const { return 0; } + virtual int IsNextstate() const { return 0; } + virtual int IsStop() const { return 0; } + virtual int IsFlush() const { return 0; } + virtual int IsCut() const { return 0; } + + virtual int IsMatch() const { return 0; } + virtual int IsMatchInput() const { return 0; } + virtual int IsMatchDiscard() const { return 0; } + virtual int IsMatchOutput() const { return 0; } + virtual int IsMatchFork() const { return 0; } + virtual int IsMatchKill() const { return 0; } + virtual int IsMatchDeliver() const { return 0; } + virtual int IsMatchInformal() const { return 0; } + virtual int IsMatchProbability() const { return 0; } + + public: + static IfTransition* TRANSITION; + +}; + +/* + * + * skip action + * + */ + +class IfSkipAction : public IfAction { + + public: + IfSkipAction(unsigned Flags = 0); + virtual ~IfSkipAction() {} + + public: + virtual int IsSkip() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + +}; + +/* + * + * informal action + * + */ + +class IfInformalAction : public IfAction { + + public: + IfInformalAction(char* Informal, + unsigned Flags = 0); + virtual ~IfInformalAction(); + + public: + const char* GetInformal() const + { return m_pInformal; } + + public: + virtual int IsInformal() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + char* m_pInformal; +}; + +/* + * + * task action + * + */ + +class IfTaskAction : public IfAction { + + public: + IfTaskAction(IfExpression* Lhs, + IfExpression* Rhs, + unsigned Flags = 0); + virtual ~IfTaskAction(); + + public: + inline IfExpression* GetLhs() const { return m_pLhs; } + inline IfExpression* GetRhs() const { return m_pRhs; } + + public: + virtual int IsTask() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pLhs; + IfExpression* m_pRhs; + +}; + +/* + * + * set action + * + */ + +class IfSetAction: public IfAction { + + public: + IfSetAction(IfExpression* Lhs, + IfExpression* Rhs, + unsigned Flags = 0); + virtual ~IfSetAction(); + + public: + inline IfExpression* GetLhs() const { return m_pLhs; } + inline IfExpression* GetRhs() const { return m_pRhs; } + + public: + virtual int IsSet() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pLhs; + IfExpression* m_pRhs; + +}; + +/* + * + * reset action + * + */ + +class IfResetAction : public IfAction { + + public: + IfResetAction(IfExpression* Lhs, + unsigned Flags = 0); + virtual ~IfResetAction(); + + public: + inline IfExpression* GetLhs() const { return m_pLhs; } + + public: + virtual int IsReset() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pLhs; + +}; + +/* + * + * input action + * + */ + +class IfInputAction : public IfAction { + + public: + IfInputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + unsigned Flags = 0); + virtual ~IfInputAction(); + + public: + inline IfSignal* GetSignal() const { return m_pSignal; } + inline IfList<IfExpression>* GetParameters() const { return m_pParameters; } + + public: + virtual int IsInput() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfSignal* m_pSignal; + IfList<IfExpression>* m_pParameters; + +}; + +/* + * + * output action + * + */ + +class IfOutputAction : public IfAction { + + public: + IfOutputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* Via, + IfExpression* To, + unsigned Flags = 0); + virtual ~IfOutputAction(); + + public: + inline IfSignal* GetSignal() const { return m_pSignal; } + inline IfList<IfExpression>* GetParameters() const { return m_pParameters; } + inline IfExpression* GetVia() const { return m_pVia; } + inline IfExpression* GetTo() const { return m_pTo; } + + public: + virtual int IsOutput() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfSignal* m_pSignal; + IfList<IfExpression>* m_pParameters; + IfExpression* m_pVia; + IfExpression* m_pTo; + +}; + +/* + * + * acquire action + * + */ + +class IfAcquireAction : public IfAction { + + public: + IfAcquireAction(IfList<IfResource>* Resources, + unsigned Flags = 0); + virtual ~IfAcquireAction(); + + public: + inline IfList<IfResource>* GetResources() const { return m_pResources; } + + public: + virtual int IsAcquire() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfList<IfResource>* m_pResources; + +}; + +/* + * + * release action + * + */ + +class IfReleaseAction : public IfAction { + + public: + IfReleaseAction(IfList<IfResource>* Resources, + unsigned Flags = 0); + virtual ~IfReleaseAction(); + + public: + inline IfList<IfResource>* GetResources() const { return m_pResources; } + + public: + virtual int IsRelease() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfList<IfResource>* m_pResources; + +}; + +/* + * + * fork action + * + */ + +class IfForkAction : public IfAction { + + public: + IfForkAction(IfExpression* Lhs, + char* Name, + IfList<IfExpression>* Parameters, + unsigned Flags = 0); + virtual ~IfForkAction(); + + public: + inline IfExpression* GetLhs() const { return m_pLhs; } + inline IfProcessEntity* GetProcess() const { return m_pProcess; } + inline IfSignalroute* GetSignalroute() const { return m_pSignalroute; } + inline IfList<IfExpression>* GetParameters() const { return m_pParameters; } + inline void SetLhs(IfExpression* Lhs) { m_pLhs = Lhs; } + + public: + virtual int IsFork() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pLhs; + IfProcessEntity* m_pProcess; + IfSignalroute* m_pSignalroute; + IfList<IfExpression>* m_pParameters; + char* m_pName; + +}; + +/* + * + * kill action + * + */ + +class IfKillAction : public IfAction { + + public: + IfKillAction(IfExpression* Rhs, + unsigned Flags = 0); + virtual ~IfKillAction(); + + public: + inline IfExpression* GetRhs() const { return m_pRhs; } + + public: + virtual int IsKill() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pRhs; +}; + +/* + * + * call action + * + */ + +class IfCallAction : public IfAction { + + public: + IfCallAction(IfExpression* Lhs, + IfProcedure* Procedure, + IfList<IfExpression>* Parameters, + unsigned Flags = 0); + virtual ~IfCallAction(); + + public: + inline IfExpression* GetLhs() const { return m_pLhs; } + inline IfProcedure* GetProcedure() const { return m_pProcedure; } + inline IfList<IfExpression>* GetParameters() const { return m_pParameters; } + + public: + virtual int IsCall() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pLhs; + IfProcedure* m_pProcedure; + IfList<IfExpression>* m_pParameters; + +}; + +/* + * + * nextstate action + * + */ + +class IfNextstateAction : public IfAction { + + public: + IfNextstateAction(IfState* State, + unsigned Flags = 0); + IfNextstateAction(char* StateName, + unsigned Flags = 0); + virtual ~IfNextstateAction(); + + public: + inline IfState* GetState() const { return m_pState; } + inline void SetState(const IfState* State) + { m_pState = (IfState*) State; } + + public: + virtual int IsNextstate() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfState* m_pState; + char* m_pStateName; + +}; + +/* + * + * stop action + * + */ + +class IfStopAction : public IfAction { + + public: + IfStopAction(unsigned Flags = 0); + virtual ~IfStopAction() {} + + public: + virtual int IsStop() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + +}; + +/* + * + * flush action + * + */ + +class IfFlushAction : public IfAction { + + public: + IfFlushAction(unsigned Flags = 0); + virtual ~IfFlushAction() {} + + public: + virtual int IsFlush() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + +}; + +/* + * + * cut action + * + */ + +class IfCutAction : public IfAction { + + public: + IfCutAction(unsigned Flags = 0); + virtual ~IfCutAction() {} + + public: + virtual int IsCut() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + +}; + + + + + + +/* + * + * Match Actions + * + */ + +class IfMatchAction : public IfAction { + +public: + IfMatchAction(unsigned Flags = 0) : IfAction(Flags) {} + virtual ~IfMatchAction() {}; + + virtual int IsMatch() const { return 1; } + +public: + virtual IfExpression* GetObsGuard() const = 0; + +}; + +/* + * + * match input action + * + */ + +class IfMatchInputAction : public IfMatchAction { + + public: + IfMatchInputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* sigvar = NULL, + IfExpression* in = NULL, + unsigned isDiscard = 0, + unsigned Flags = 0); + virtual ~IfMatchInputAction(); + + public: + inline IfSignal* GetSignal() const { return m_pSignal; } + inline IfList<IfExpression>* GetParameters() const { return m_pParameters; } + + public: + virtual int IsMatchInput() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual IfExpression* GetObsGuard() const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfSignal* m_pSignal; + IfList<IfExpression>* m_pParameters; + IfExpression* m_pSigvar; + IfExpression* m_pIn; + unsigned m_nIsDiscard; + +}; + +/* + * + * match output action + * + */ + +class IfMatchOutputAction : public IfMatchAction { + + public: + IfMatchOutputAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* sigvar = NULL, + IfExpression* ord = NULL, + IfExpression* from = NULL, + IfExpression* via = NULL, + IfExpression* to = NULL, + unsigned Flags = 0); + virtual ~IfMatchOutputAction(); + + public: + inline IfSignal* GetSignal() const { return m_pSignal; } + inline IfList<IfExpression>* GetParameters() const { return m_pParameters; } + + public: + virtual int IsMatchOutput() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual IfExpression* GetObsGuard() const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfSignal* m_pSignal; + IfList<IfExpression>* m_pParameters; + IfExpression* m_pSigvar; + IfExpression* m_pOrd; + IfExpression* m_pFrom; + IfExpression* m_pVia; + IfExpression* m_pTo; + +}; + +/* + * + * match fork action + * + */ + +class IfMatchForkAction : public IfMatchAction { + + public: + IfMatchForkAction(char* name = NULL, + IfExpression* var = NULL, + IfExpression* in = NULL, + unsigned Flags = 0); + virtual ~IfMatchForkAction(); + + public: + virtual int IsMatchFork() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual IfExpression* GetObsGuard() const; + + protected: + IfProcessEntity *m_pProcess; + char* m_pName; + IfExpression* m_pIn; + IfExpression* m_pVar; + +}; + +/* + * + * match kill action + * + */ + +class IfMatchKillAction : public IfMatchAction { + + public: + IfMatchKillAction(char* name = NULL, + IfExpression* var = NULL, + IfExpression* in = NULL, + unsigned Flags = 0); + virtual ~IfMatchKillAction(); + + public: + virtual int IsMatchKill() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual IfExpression* GetObsGuard() const; + + protected: + char *m_pName; + IfProcessEntity *m_pProcess; + IfExpression* m_pIn; + IfExpression* m_pVar; + +}; + +/* + * + * match deliver action + * + */ + +class IfMatchDeliverAction : public IfMatchAction { + + public: + IfMatchDeliverAction(IfSignal* Signal, + IfList<IfExpression>* Parameters, + IfExpression* sigvar = NULL, + IfExpression* from = NULL, + unsigned Flags = 0); + virtual ~IfMatchDeliverAction(); + + public: + inline IfSignal* GetSignal() const { return m_pSignal; } + inline IfList<IfExpression>* GetParameters() const { return m_pParameters; } + + public: + virtual int IsMatchDeliver() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual IfExpression* GetObsGuard() const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfSignal* m_pSignal; + IfList<IfExpression>* m_pParameters; + IfExpression* m_pSigvar; + IfExpression* m_pFrom; + +}; + +/* + * + * match informal action + * + */ + +class IfMatchInformalAction : public IfMatchAction { + + public: + IfMatchInformalAction(char* name, + IfExpression* in = NULL, + unsigned Flags = 0); + virtual ~IfMatchInformalAction(); + + public: + virtual int IsMatchInformal() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual IfExpression* GetObsGuard() const; + + protected: + char* m_pName; + IfExpression* m_pIn; + +}; + +/* + * + * match probability action + * + */ + +class IfMatchProbabilityAction : public IfMatchAction { + + public: + IfMatchProbabilityAction(IfExpression* var = NULL, + unsigned Flags = 0); + virtual ~IfMatchProbabilityAction(); + + public: + virtual int IsMatchProbability() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual IfExpression* GetObsGuard() const; + + protected: + IfExpression* m_pVar; + +}; + diff --git a/src/model/constant.C b/src/model/constant.C new file mode 100644 index 0000000000000000000000000000000000000000..410521266325f794481ae5b3d64037788184849b --- /dev/null +++ b/src/model/constant.C @@ -0,0 +1,252 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of constants + * + */ + +#include "model.h" + +IfConstant::IfConstant(char* Name, + unsigned Flags) + : IfObject(Name, Flags) { + m_pType = NULL; +} + +void IfConstant::Dump(FILE* file) const { + fprintf(file, "const %s = ", m_pName); + DumpValue(file); + fprintf(file, ";"); +} + +void IfConstant::DumpValue(FILE*) const { + // pure virtual +} + +void IfConstant::DumpNameOrValue(FILE* file) const { + if (m_pName) + fprintf(file, "%s", m_pName); + else + DumpValue(file); +} + +void IfConstant::PostCompile() { + if (m_pType == NULL) { + SetFlag(CORRECT, 0); + Protest("undefined type"); + } + IfObject::PostCompile(); +} + +void IfConstant::Code(FILE* file) const { + fprintf(file, "code(constant,%s,", m_pName); + CodeValue(file); + fprintf(file, ")"); +} + +void IfConstant::CodeValue(FILE*) const { + // pure virtual +} + +void IfConstant::CodeNameOrValue(FILE* file) const { + if (m_pName) + fprintf(file, "constant_name(%s)", m_pName); + else + CodeValue(file); +} + +/* + * + * implementation of integer-valued constants + * + */ + +IfIntegerConstant::IfIntegerConstant(int Value, + char* Name, + unsigned Flags) + : IfConstant(Name, Flags) { + m_iValue = Value; +} + +void IfIntegerConstant::DumpValue(FILE* file) const { + fprintf(file, "%d", m_iValue); +} + +void IfIntegerConstant::PreCompile() { + IfConstant::PreCompile(); + m_pType = TYPES[IfBasicType::INTEGER]; +} + +void IfIntegerConstant::CodeValue(FILE* file) const { + fprintf(file, "%d", m_iValue); +} + +/* + * + * implementation of real-valued constants + * + */ + +IfRealConstant::IfRealConstant(float Value, + char* Name, + unsigned Flags) + : IfConstant(Name, Flags) { + m_fValue = Value; +} + +void IfRealConstant::DumpValue(FILE* file) const { + fprintf(file, "%f", m_fValue); +} + +void IfRealConstant::PreCompile() { + IfConstant::PreCompile(); + m_pType = TYPES[IfBasicType::REAL]; +} + +void IfRealConstant::CodeValue(FILE* file) const { + fprintf(file, "%f", m_fValue); +} + +/* + * + * implementation of boolean-valued constants + * + */ + +IfBooleanConstant::IfBooleanConstant(EValue Value, + char* Name, + unsigned Flags) + : IfConstant(Name, Flags) { + m_eValue = Value; +} + +void IfBooleanConstant::DumpValue(FILE* file) const { + fprintf(file, "%s", m_eValue == TRUE ? "true" : "false"); +} + +void IfBooleanConstant::PreCompile() { + IfConstant::PreCompile(); + m_pType = TYPES[IfBasicType::BOOLEAN]; +} + +void IfBooleanConstant::CodeValue(FILE* file) const { + fprintf(file, "if_boolean_%s", m_eValue == TRUE ? "true" : "false"); +} + +/* + * + * implementation of pid-valued constants + * + */ + +IfPidConstant::IfPidConstant(EValue Value, + char* Name, + unsigned Flags) + : IfConstant(Name, Flags) { + m_eValue = Value; +} + +void IfPidConstant::DumpValue(FILE* file) const { + fprintf(file, "%s", m_eValue == NIL ? "nil" : "self"); +} + +void IfPidConstant::PreCompile() { + IfConstant::PreCompile(); + m_pType = TYPES[IfBasicType::PID]; +} + +void IfPidConstant::CodeValue(FILE* file) const { + fprintf(file, "%s", m_eValue == NIL ? "if_pid_nil" : "m_pid"); +} + +/* + * + * implementation of enum-valued constants + * + */ + +IfEnumConstant::IfEnumConstant(char* Name, + unsigned Flags) + : IfConstant(Name, Flags) { + m_iValue = -1; +} + +void IfEnumConstant::DumpValue(FILE* file) const { + fprintf(file, "%s", m_pName); +} + +void IfEnumConstant::PreCompile() { + IfConstant::PreCompile(); + m_pType = (IfType*) CONTEXT.Top(-1); +} + +void IfEnumConstant::CodeValue(FILE* file) const { + fprintf(file, "constant_name(%s)", m_pName); +} + + +/* + * + * implementation of other-valued constants + * + */ + +IfOtherConstant::IfOtherConstant(IfConstant* Other, + char* Name, + unsigned Flags) + : IfConstant(Name, Flags) { + m_pOther = Other; +} + +void IfOtherConstant::DumpValue(FILE* file) const { + fprintf(file, "%s", m_pOther->GetName()); +} + +void IfOtherConstant::PreCompile() { + IfConstant::PreCompile(); + m_pType = m_pOther->GetType(); +} + +void IfOtherConstant::CodeValue(FILE* file) const { + fprintf(file, "constant_name(%s)", m_pOther->GetName()); +} + diff --git a/src/model/constant.h b/src/model/constant.h new file mode 100644 index 0000000000000000000000000000000000000000..e0e1ff4b8b5f39f4051ec14c5cd4518c19eab0eb --- /dev/null +++ b/src/model/constant.h @@ -0,0 +1,261 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract constant interface + * + */ + +class IfConstant : public IfObject { + + public: + IfConstant(char* Name = NULL, + unsigned Flags = 0); + virtual ~IfConstant() {} + + public: + inline IfType* GetType() const { return m_pType; } + virtual IfConstant* GetBase() const { return (IfConstant*) this; } + + public: + virtual const char* GetClass() const { return "constant"; } + + virtual int IsBoolean() const { return 0; } + virtual int IsInteger() const { return 0; } + virtual int IsReal() const { return 0; } + virtual int IsPid() const { return 0; } + virtual int IsEnum() const { return 0; } + virtual int IsOther() const { return 0; } + + public: + virtual void Dump(FILE* file) const; + virtual void DumpValue(FILE* file) const; + virtual void DumpNameOrValue(FILE* file) const; + + virtual void PostCompile(); + + virtual void Code(FILE* file) const; + virtual void CodeValue(FILE* file) const; + virtual void CodeNameOrValue(FILE* file) const; + + protected: + IfType* m_pType; + +}; + +/* + * + * defines boolean-valued constants : false, true + * + */ + +class IfBooleanConstant : public IfConstant { + + public: + enum EValue {FALSE, TRUE}; + + public: + IfBooleanConstant(EValue Value, + char* Name = NULL, + unsigned Flags = 0); + virtual ~IfBooleanConstant() {} + + public: + inline EValue GetValue() const { return m_eValue; } + inline void SetValue(const EValue Value) { m_eValue = Value; } + + public: + virtual int IsBoolean() const { return 1; } + virtual void DumpValue(FILE* file) const; + virtual void PreCompile(); + virtual void CodeValue(FILE* file) const; + + protected: + EValue m_eValue; + +}; + +/* + * + * defines integer-valued constants : 0, 1, 2, 3 ... + * + */ + +class IfIntegerConstant : public IfConstant { + + public: + IfIntegerConstant(int Value, + char* Name = NULL, + unsigned Flags = 0); + virtual ~IfIntegerConstant() {} + + public: + inline int GetValue() const { return m_iValue; } + inline void SetValue(const int Value) { m_iValue = Value; } + + public: + virtual int IsInteger() const { return 1; } + virtual void DumpValue(FILE* file) const; + virtual void PreCompile(); + virtual void CodeValue(FILE* file) const; + + protected: + int m_iValue; + +}; + +/* + * + * defines real-valued constants : 0.00, 0.01, ... + * + */ + +class IfRealConstant : public IfConstant { + + public: + IfRealConstant(float Value, + char* Name = NULL, + unsigned Flags = 0); + virtual ~IfRealConstant() {} + + public: + inline float GetValue() const { return m_fValue; } + inline void SetValue(const float Value) { m_fValue = Value; } + + public: + virtual int IsReal() const { return 1; } + virtual void DumpValue(FILE* file) const; + virtual void PreCompile(); + virtual void CodeValue(FILE* file) const; + + protected: + float m_fValue; + +}; + +/* + * + * defines pid-valued constants : null, self + * + */ + +class IfPidConstant : public IfConstant { + + public: + enum EValue {NIL, SELF}; + + public: + IfPidConstant(EValue Value, + char* Name = NULL, + unsigned Flags = 0); + virtual ~IfPidConstant() {} + + public: + inline EValue GetValue() const { return m_eValue; } + inline void SetValue(const EValue Value) { m_eValue = Value; } + + public: + virtual int IsPid() const { return 1; } + virtual void DumpValue(FILE* file) const; + virtual void PreCompile(); + virtual void CodeValue(FILE* file) const; + + protected: + EValue m_eValue; + +}; + +/* + * + * defines enum-valued constants + * + */ + +class IfEnumConstant : public IfConstant { + + public: + IfEnumConstant(char* Name, + unsigned Flags = 0); + virtual ~IfEnumConstant() {} + + public: + inline int GetValue() const { return m_iValue; } + inline void SetValue(const int Value) { m_iValue = Value; } + + public: + virtual int IsEnum() const { return 1; } + virtual void DumpValue(FILE* file) const; + virtual void PreCompile(); + virtual void CodeValue(FILE* file) const; + + protected: + int m_iValue; + +}; + +/* + * + * defines other-constant constants [rename] + * + */ + +class IfOtherConstant : public IfConstant { + + public: + IfOtherConstant(IfConstant* Other, + char* Name, + unsigned Flags = 0); + virtual ~IfOtherConstant() {} + + public: + inline IfConstant* GetOther() const { return m_pOther; } + virtual IfConstant* GetBase() const { return m_pOther->GetBase(); } + + public: + virtual int IsOther() const { return 1; } + virtual void DumpValue(FILE* file) const; + virtual void PreCompile(); + virtual void CodeValue(FILE* file) const; + + protected: + IfConstant* m_pOther; + +}; diff --git a/src/model/constraint.C b/src/model/constraint.C new file mode 100644 index 0000000000000000000000000000000000000000..01e4861489b861252c580bba2fcfc34d2e766bc6 --- /dev/null +++ b/src/model/constraint.C @@ -0,0 +1,226 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of constraints + * + */ + +#include "model.h" + +IfConstraint::IfConstraint(unsigned Flags) + : IfObject(NULL, Flags) { +} + +IfConstraint::~IfConstraint() { +} + +int IfConstraint::Use(const IfVariable* Variable) const { + // pure virtual + return 0; +} + +int IfConstraint::Def(const IfVariable* Variable) const { + return 0; +} + +/* + * + * basic constraint interface + * + */ + +IfExpression::Operator IfBasicConstraint::OPERATOR[] = { + { "<", "lt", 0, 2}, + {"<=", "le", 0, 2}, + { "=", "eq", 0, 2}, + {">=", "ge", 0, 2}, + { ">", "gt", 0, 2} +}; + +IfBasicConstraint::IfBasicConstraint(IfExpression* X, + IfExpression* Y, + EOperator Operator, + IfExpression* K, + unsigned Flags) + : IfConstraint(Flags) { + // grammar patch - confusing expressions... + if (X != NULL && Y == NULL && + X->IsBinary()) { + IfBinaryExpression* x = (IfBinaryExpression*) X; + if (x->GetOperator() == IfBinaryExpression::MINUS) { + X = x->GetLeft(); + Y = x->GetRight(); + } + } + // end grammar patch + m_pX = X; + m_pY = Y; + m_eOperator = Operator; + m_pK = K; +} + +IfBasicConstraint::~IfBasicConstraint() { + if (m_pX) delete m_pX; + if (m_pY) delete m_pY; + if (m_pK) delete m_pK; +} + +void IfBasicConstraint::Dump(FILE* file) const { + if (m_pX) + m_pX->Dump(file); + if (m_pY) { + fprintf(file, "-"); + m_pY->Dump(file); + } + fprintf(file, "%s", OPERATOR[m_eOperator].name); + if (m_pK) + m_pK->Dump(file); +} + +void IfBasicConstraint::PreCompile() { + IfConstraint::PreCompile(); + + IfType* integer = TYPES.GetAt(IfBasicType::INTEGER); + IfType* real = TYPES.GetAt(IfBasicType::REAL); + IfType* clock = TYPES.GetAt(IfBasicType::CLOCK); + + int ok = 1; + + if (m_pX) { + ok &= m_pX->Compile(); + ok &= m_pX->IsReference(); + if (m_pX->GetType()) + ok &= m_pX->GetType()->Match(clock); + } + if (m_pY) { + ok &= m_pY->Compile(); + ok &= m_pY->IsReference(); + if (m_pY->GetType()) + ok &= m_pY->GetType()->Match(clock); + } + if (m_pK) { + ok &= m_pK->Compile(); + ok &= !m_pK->IsTimed(); + if (m_pK->GetType()) { + ok &= m_pK->GetType()->Match(integer, real); + if (m_pK->GetType()->Match(real)) + Protest("real-value in clock constraint"); + } + } + + ok &= (m_pX || m_pY) && m_pK; + + SetFlag(CORRECT, ok); + SetFlag(TIMED, 1); + +} + +void IfBasicConstraint::Code(FILE* file) const { + if (m_eOperator == LT || m_eOperator == LE || m_eOperator == EQ) { + fprintf(file, "constraint("); + if (m_pX) m_pX->Code(file); else fprintf(file, "0"); + fprintf(file, ","); + if (m_pY) m_pY->Code(file); else fprintf(file, "0"); + fprintf(file, ",2*((int) "); m_pK->Code(file); fprintf(file, ")"); + if (m_eOperator != LT) fprintf(file, "+1"); + fprintf(file, ")"); + } + if (m_eOperator == EQ) + fprintf(file, ","); + if (m_eOperator == EQ || m_eOperator == GE || m_eOperator == GT) { + fprintf(file, "constraint("); + if (m_pY) m_pY->Code(file); else fprintf(file, "0"); + fprintf(file, ","); + if (m_pX) m_pX->Code(file); else fprintf(file, "0"); + fprintf(file, ",-2*("); m_pK->Code(file); fprintf(file, ")"); + if (m_eOperator != GT) fprintf(file, "+1"); + fprintf(file, ")"); + } +} + +int IfBasicConstraint::Use(const IfVariable* Variable) const { + int use = 0; + if (m_pX) use |= m_pX->Use(Variable); + if (m_pY) use |= m_pY->Use(Variable); + if (m_pK) use |= m_pK->Use(Variable); + return use; +} + +/* + * + * composed constraints implementation + * + */ + +IfComposedConstraint::IfComposedConstraint(IfList<IfBasicConstraint>* Constraints, + unsigned Flags) + : IfConstraint(Flags) { + m_pConstraints = Constraints; +} + +IfComposedConstraint::~IfComposedConstraint() { + delete m_pConstraints; +} + +void IfComposedConstraint::Dump(FILE* file) const { + m_pConstraints->Dump(file, "", " and ", ""); +} + +void IfComposedConstraint::PreCompile() { + IfConstraint::PreCompile(); + + int ok = m_pConstraints->Compile(); + + SetFlag(CORRECT, ok); + SetFlag(TIMED, 1); +} + +void IfComposedConstraint::Code(FILE* file) const { + m_pConstraints->Code(file, "", ",", ""); +} + +int IfComposedConstraint::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pConstraints->GetCount() && !use; i++) + use |= m_pConstraints->GetAt(i)->Use(Variable); + return use; +} diff --git a/src/model/constraint.h b/src/model/constraint.h new file mode 100644 index 0000000000000000000000000000000000000000..1f5712ee1e76930c958ec860770ee85b53de4410 --- /dev/null +++ b/src/model/constraint.h @@ -0,0 +1,145 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract constraint interface + * + */ + +class IfConstraint : public IfObject { + + public: + IfConstraint(unsigned Flags = 0); + virtual ~IfConstraint(); + + public: + virtual const char* GetClass() const + { return "constraint"; } + virtual int IsConstraint() const + { return 1; } + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + public: + virtual int IsBasic() const { return 0; } + virtual int IsComposed() const { return 0; } + +}; + +/* + * + * basic constraints interface + * + */ + +class IfBasicConstraint : public IfConstraint { + + public: + enum EOperator { LT, LE, EQ, GE, GT }; + + public: + IfBasicConstraint(IfExpression* X, + IfExpression* Y, + EOperator Operator, + IfExpression* K, + unsigned Flags = 0); + virtual ~IfBasicConstraint(); + + public: + inline EOperator GetOperator() const { return m_eOperator; } + inline IfExpression* GetX() const { return m_pX; } + inline IfExpression* GetY() const { return m_pY; } + inline IfExpression* GetK() const { return m_pK; } + inline void SetOperator(const EOperator Operator) { m_eOperator = Operator; } + + public: + virtual int IsBasic() const { return 1; } + + public: + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + public: + static IfExpression::Operator OPERATOR[]; + + protected: + EOperator m_eOperator; + IfExpression* m_pX; + IfExpression* m_pY; + IfExpression* m_pK; +}; + +/* + * + * composed constraints interface + * + */ + +class IfComposedConstraint : public IfConstraint { + + public: + IfComposedConstraint(IfList<IfBasicConstraint>* Constraints, + unsigned Flags = 0); + virtual ~IfComposedConstraint(); + + public: + inline IfList<IfBasicConstraint>* GetConstraints() const + { return m_pConstraints; } + virtual int IsComposed() const { return 1; } + + public: + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + protected: + IfList<IfBasicConstraint>* m_pConstraints; + +}; diff --git a/src/model/entity.C b/src/model/entity.C new file mode 100644 index 0000000000000000000000000000000000000000..e0e5bee636c13b44fe4f44fc3c68646149ad9134 --- /dev/null +++ b/src/model/entity.C @@ -0,0 +1,595 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of entities + * + */ + +#include "model.h" + +IfEntity::IfEntity(IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags) + : IfObject(Name, Flags) { + m_pConstants = Constants; + m_pTypes = Types; + m_pVariables = Variables; + m_pProcedures = Procedures; +} + +IfEntity::~IfEntity() { + delete m_pConstants; + delete m_pTypes; + delete m_pVariables; + delete m_pProcedures; +} + +void IfEntity::PreCompile() { + IfObject::PreCompile(); + + int ok = 1; + int i; + + for(i = 0; i < m_pTypes->GetCount(); i++) + if (m_pTypes->GetAt(i)->IsEnum()) + ok &= m_pTypes->GetAt(i)->Compile(); + + ok &= m_pConstants->Compile(); + + for(i = 0; i < m_pTypes->GetCount(); i++) + if (!m_pTypes->GetAt(i)->IsEnum()) + ok &= m_pTypes->GetAt(i)->Compile(); + + ok &= m_pVariables->Compile(); + + ok &= m_pProcedures->Compile(); + + SetFlag(CORRECT, ok); +} + +void IfEntity::Code(FILE* file) const { + if (IsSystem()) + fprintf(file, "code(system,%s)\n", m_pName); + + m_pConstants->Code(file, "\n", "\n", "\n"); + m_pTypes->Code(file, "\n", "\n", "\n"); +} + +/* + * + * system entity + * + */ + +IfSystemEntity::IfSystemEntity(IfList<IfProcessEntity>* Processes, + IfList<IfPriorityRuleEntity>* PriorityRules, + IfList<IfObserverEntity>* Observers, + IfList<IfSignalroute>* Signalroutes, + IfList<IfSignal>* Signals, + IfList<IfResource>* Resources, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags) + : IfEntity(Constants, Types, Variables, Procedures, Name, Flags) { + m_pProcesses = Processes; + m_pPriorityRules = PriorityRules; + m_pObservers = Observers; + m_pSignalroutes = Signalroutes; + m_pSignals = Signals; + m_pResources = Resources; +} + +IfSystemEntity::~IfSystemEntity() { + delete m_pProcesses; + delete m_pPriorityRules; + delete m_pSignalroutes; + delete m_pSignals; + delete m_pResources; +} + +void IfSystemEntity::Dump(FILE* file) const { + fprintf(file, "system %s;\n", m_pName); + m_pConstants->Dump(file, "\n", "\n", "\n"); + m_pTypes->Dump(file, "\n", "\n", "\n"); + m_pVariables->Dump(file, "\n", "\n", "\n"); + m_pResources->Dump(file, "\n", "\n", "\n"); + m_pSignals->Dump(file, "\n", "\n", "\n"); + m_pSignalroutes->Dump(file, "\n", "\n", "\n"); + m_pProcedures->Dump(file, "\n\n", "\n\n", "\n"); + m_pProcesses->Dump(file, "\n\n", "\n\n", "\n"); + fprintf(file, "endsystem;\n"); + m_pObservers->Dump(file, "\n\n", "\n\n", "\n"); + m_pPriorityRules->Dump(file, "\n\npriorityrules\n", "\n\n", "\nendpriorityrules;\n"); +} + +void IfSystemEntity::PreCompile() { + IfEntity::PreCompile(); + + int ok = 1, index = 0; + + ok &= m_pResources->Compile(); + + ok &= m_pSignals->Compile(); + + ok &= m_pSignalroutes->Compile(); + for(int i = 0; i < m_pSignalroutes->GetCount(); i++) { + IfSignalroute* route = m_pSignalroutes->GetAt(i); + if (route->GetFrom() != NULL) + route->GetFrom()->Link(route); + if (route->GetTo() != NULL && route->GetTo() != route->GetFrom()) + route->GetTo()->Link(route); + } + + ok &= m_pProcesses->Compile(); + + ok &= m_pPriorityRules->Compile(); + + ok &= m_pObservers->Compile(); + + SetFlag(CORRECT, ok); + + SetFlag(TIMED, m_pProcesses->GetFlag(TIMED)); + + index = 0; + m_pResources->SetIndex(&index); + index = 0; + m_pSignals->SetIndex(&index); + index = 0; + m_pPriorityRules->SetIndex(&index); + index = 1; // 0 reserved (for nil) + m_pSignalroutes->SetIndex(&index); + m_pProcesses->SetIndex(&index); + m_pObservers->SetIndex(&index); + + if (TRANSFORM & XSCOPE) + for(int i = 0; i < m_pProcesses->GetCount(); i++) { + IfProcessEntity* process = m_pProcesses->GetAt(i); + for(int j = 0; j < process->GetVariables()->GetCount(); j++) { + IfVariable* variable = process->GetVariables()->GetAt(j); + if (variable->IsPublic() && !variable->GetFlag(IfVariable::IMPORTED)) + variable->SetScope(IfVariable::PRIVATE); + } + } +} + +void IfSystemEntity::Code(FILE* file) const { + int i, next; + + IfEntity::Code(file); + + if (m_pVariables->GetCount()) + Protest("global variables are not supported"); + + m_pResources->Code(file, "\n", "\n", "\n"); + + m_pSignals->Code(file, "\n", "\n", "\n"); + m_pSignalroutes->Code(file, "\n", "\n", "\n"); + + fprintf(file, "\n"); + fprintf(file, "code(system_instance, %s)\n", m_pName); + m_pProcedures->Code(file, "\n", "\n", "\n"); + fprintf(file, "code(end_system_instance)\n"); + + m_pProcesses->Code(file, "\n", "\n", "\n"); + + m_pObservers->Code(file, "\n", "\n", "\n"); + + if(m_pObservers->GetCount()) { + fprintf(file, "define(`x_use_priorities', `1')\n"); + } else { + fprintf(file, "define(`x_use_priorities', `0')\n"); + } + + fprintf(file, "code(start,("); + for(i = 0, next = 0; i < m_pSignalroutes->GetCount(); i++) { + IfSignalroute* route = m_pSignalroutes->GetAt(i); + int k = ((IfIntegerConstant*) route->GetInstances()->GetBase())->GetValue(); + if (route->GetTo() == NULL || route->GetFrom() == NULL) + continue; + for(int j = 0; j < k; j++, next++) + fprintf(file, "%s%s", next ? "," : "", route->GetName()); + } + fprintf(file, "),("); + for(i = 0, next = 0; i < m_pProcesses->GetCount(); i++) { + IfProcessEntity* process = m_pProcesses->GetAt(i); + int k = ((IfIntegerConstant*) process->GetInstances()->GetBase())->GetValue(); + for(int j = 0; j < k; j++, next++) + fprintf(file, "%s%s", next ? "," : "", process->GetName()); + } + for(i = 0; i < m_pObservers->GetCount(); i++) { + IfObserverEntity* obs = m_pObservers->GetAt(i); + fprintf(file, "%s%s", next++ ? "," : "", obs->GetName()); + } + fprintf(file, "),%s,time)", + m_pResources->GetCount() ? "monitor" : ""); + + //priority rules + fprintf(file, "code(priority_rule_begin, %d)\n", m_pPriorityRules->GetCount()+1); + m_pPriorityRules->Code(file,"\n","\n","\n"); + fprintf(file,"code(priority_rule_null, %d)",m_pPriorityRules->GetCount()); +} + +void IfSystemEntity::CreateSigUnionType() { + int i,j; + for(j = 0; j < GetSignals()->GetCount(); j++) { + IfList<IfVariable>* vl = new IfList<IfVariable>(1); + char s[256]; + + for(int i=0; i<GetSignals()->GetAt(j)->GetParameters()->GetCount(); i++) { + char c[16]; + sprintf(c, "p%d", i+1); + vl->Add(new IfVariable(IfVariable::FIELD, + IfVariable::NOSCOPE, + IfVariable::NOMODE, + GetSignals()->GetAt(j)->GetParameters()->GetAt(i), NULL, strdup(c))); + } + sprintf(s, "t_%s", GetSignals()->GetAt(j)->GetName()); + IfRecordType* rt = new IfRecordType(vl, strdup(s), IfType::PREDEFINED); + GetTypes()->Add(rt); + } + + IfList<IfVariable>* vl = new IfList<IfVariable>(1); + char un[256]; + + for(i = 0; i < GetSignals()->GetCount(); i++) { + char sn[256]; + char st[256]; + sprintf(sn, "%s", GetSignals()->GetAt(i)->GetName()); + sprintf(st, "t_%s", GetSignals()->GetAt(i)->GetName()); + + IfType* t = GetTypes()->Find(st); + assert(t != NULL); + + vl->Add(new IfVariable(IfVariable::FIELD, + IfVariable::NOSCOPE, + IfVariable::NOMODE, + t, NULL, strdup(sn))); + + } + sprintf(un, "t_if_signal"); + IfUnionType* su = new IfUnionType(vl, strdup(un), 1, IfType::PREDEFINED); + GetTypes()->Add(su); +} + + +/* + * + * automaton entity + * + */ + +IfAutomatonEntity::IfAutomatonEntity(IfList<IfState>* States, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags) + : IfEntity(Constants, Types, Variables, Procedures, Name, Flags) { + char* options[] = {(char*) "#start", NULL}; + + m_pStates = States; + + m_pEntry = new IfState(NULL, + new IfList<IfSignal>, + new IfList<IfTransition>, + m_pStates, + options, + strdup("top")); + m_pControl = new IfList<IfState>; +} + +IfAutomatonEntity::~IfAutomatonEntity() { + delete m_pEntry; + delete m_pControl; +} + +/* + * + * process entity + * + */ + +IfProcessEntity::IfProcessEntity(IfConstant* Instances, + IfList<IfVariable>* Parameters, + IfList<IfState>* States, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags) + : IfAutomatonEntity(States, Constants, Types, Variables, Procedures, Name, Flags) { + m_pInstances = Instances; + m_pParameters = Parameters; + + m_pInRoutes = new IfList<IfSignalroute>; + m_pOutRoutes = new IfList<IfSignalroute>; + m_pInSignals = new IfList<IfSignal>; + m_pOutSignals = new IfList<IfSignal>; + m_pEnvSignals = new IfList<IfSignal>; +} + +IfProcessEntity::~IfProcessEntity() { + delete m_pInstances; + delete m_pParameters; + + delete m_pInRoutes; + delete m_pOutRoutes; + delete m_pInSignals; + delete m_pOutSignals; + delete m_pEnvSignals; +} + +void IfProcessEntity::Dump(FILE* file) const { + + fprintf(file, "process %s(", m_pName); + m_pInstances->DumpNameOrValue(file); + fprintf(file, ");\n"); + if (m_pParameters->GetCount()) + m_pParameters->Dump(file, " fpar ", ", ", ";\n"); + m_pConstants->Dump(file, "\n", "\n", "\n"); + m_pTypes->Dump(file, "\n", "\n", "\n"); + m_pVariables->Dump(file, "\n", "\n", "\n"); + m_pProcedures->Dump(file, "\n", "\n", "\n"); + m_pStates->Dump(file, "\n", "\n", "\n"); + fprintf(file, "endprocess;"); +} + +void IfProcessEntity::Link(IfSignalroute* route) { + + if (route->GetTo() == this) + m_pInRoutes->Add(route); + if (route->GetFrom() == this) + m_pOutRoutes->Add(route); + + for(int i = 0; i < route->GetSignals()->GetCount(); i++) { + IfSignal* signal = route->GetSignals()->GetAt(i); + if (route->GetTo() == this) { + if (m_pInSignals->Find(signal) == NULL) + m_pInSignals->Add(signal); + if (route->GetFrom() == NULL && + m_pEnvSignals->Find(signal) == NULL) + m_pEnvSignals->Add(signal); + } + if (route->GetFrom() == this) + if (m_pOutSignals->Find(signal) == NULL) + m_pOutSignals->Add(signal); + } + +} + +void IfProcessEntity::PreCompile() { + IfEntity::PreCompile(); + + int ok = 1, index = 0; + + ok &= m_pInstances->Compile(); + ok &= m_pInstances->GetBase()->IsInteger(); + + ok &= m_pParameters->Compile(); + + m_pEntry->SetParent( NULL ); + + ok &= m_pEntry->Compile(); + + m_pSystem = (IfSystemEntity*) CONTEXT[0]; + + SetFlag(CORRECT, ok); + + SetFlag(TIMED, m_pParameters->GetFlag(TIMED) || + m_pVariables->GetFlag(TIMED)); + + m_pEntry->SetIndex(&index); +} + +void IfProcessEntity::Code(FILE* file) const { + int i,k; + + IfEntity::Code(file); + + int L = m_pSystem->GetSignals()->GetCount(); + + fprintf(file, "code(instance,%s,%d,\n\t(", + m_pName, m_iIndex); + for(i = 0; i < m_pParameters->GetCount(); i++) { + IfVariable* variable = (IfVariable*) m_pParameters->GetAt(i); + fprintf(file, "%s,%s", variable->GetName(), variable->GetType()->GetName()); + if (i < m_pParameters->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "),\n\t("); + for(i = 0; i < m_pVariables->GetCount(); i++) { + IfVariable* variable = (IfVariable*) m_pVariables->GetAt(i); + fprintf(file, "%s,%s", variable->GetName(), variable->GetType()->GetName()); + if (i < m_pVariables->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "),\n\t("); + for(i = 0, k = 0; i < m_pVariables->GetCount(); i++) { + IfVariable* variable = (IfVariable*) m_pVariables->GetAt(i); + if (variable->GetInitializer()) { + fprintf(file, "%s%s,%s,", k++ ? "," : "", + variable->GetName(), variable->GetType()->GetName()); + variable->GetInitializer()->Code(file); + } + } + fprintf(file, "),\n\t("); + for(int i = 0; i < m_pControl->GetCount(); i++) { + IfState* state = m_pControl->GetAt(i); + fprintf(file, "%s%s,integer", i ? ",": "", state->GetName()); + } + fprintf(file,"),("); + m_pEntry->CodeExit(file); + m_pEntry->CodeEntry(file); + fprintf(file, "),\n\t("); + for(i = 0; i < m_pEnvSignals->GetCount(); i++) { + IfSignal* signal = m_pEnvSignals->GetAt(i); + fprintf(file, "%s", signal->GetName()); + if (i < m_pEnvSignals->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "))\n\n"); + + m_pProcedures->Code(file, "\n", "\n", "\n\n"); + + m_pEntry->Code(file); + + fprintf(file, "code(instance_table,%d,`\n", L+1); + m_pEntry->CodeTable(file); + fprintf(file, "')\n\n"); + + fprintf(file, "code(end_instance)\n\n"); +} + +/* + * + * observer entity + * + */ + +IfObserverEntity::IfObserverEntity(EObsKind kind, + IfList<IfState>* States, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags) + : IfAutomatonEntity(States, Constants, Types, Variables, Procedures, Name, Flags) { + + m_kind = kind; +} + +IfObserverEntity::~IfObserverEntity() { +} + +void IfObserverEntity::Dump(FILE* file) const { + + switch(m_kind) { + case PURE: fprintf(file, "pure "); break; + case CUT: fprintf(file, "cut "); break; + case INTRUSIVE: fprintf(file, "intrusive "); break; + } + fprintf(file, "observer %s", m_pName); + fprintf(file, ";\n"); + m_pConstants->Dump(file, "\n", "\n", "\n"); + m_pTypes->Dump(file, "\n", "\n", "\n"); + m_pVariables->Dump(file, "\n", "\n", "\n"); + m_pProcedures->Dump(file, "\n", "\n", "\n"); + m_pStates->Dump(file, "\n", "\n", "\n"); + fprintf(file, "endobserver;"); +} + +void IfObserverEntity::PreCompile() { + IfEntity::PreCompile(); + + int ok = 1, index = 0; + + m_pEntry->SetParent( NULL ); + + ok &= m_pEntry->Compile(); + + m_pSystem = (IfSystemEntity*) CONTEXT[0]; + + SetFlag(CORRECT, ok); + + SetFlag(TIMED, m_pVariables->GetFlag(TIMED)); + + m_pEntry->SetIndex(&index); +} + +void IfObserverEntity::Code(FILE* file) const { + int i,k; + + IfEntity::Code(file); + + int L = m_pSystem->GetSignals()->GetCount(); + + fprintf(file, "code(obsinstance,%s,%d,(),", + m_pName, m_iIndex); + fprintf(file, "\n\t("); + for(i = 0; i < m_pVariables->GetCount(); i++) { + IfVariable* variable = (IfVariable*) m_pVariables->GetAt(i); + fprintf(file, "%s,%s", variable->GetName(), variable->GetType()->GetName()); + if (i < m_pVariables->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "),\n\t("); + for(i = 0, k = 0; i < m_pVariables->GetCount(); i++) { + IfVariable* variable = (IfVariable*) m_pVariables->GetAt(i); + if (variable->GetInitializer()) { + fprintf(file, "%s%s,%s,", k++ ? "," : "", + variable->GetName(), variable->GetType()->GetName()); + variable->GetInitializer()->Code(file); + } + } + fprintf(file, "),\n\t("); + for(int i = 0; i < m_pControl->GetCount(); i++) { + IfState* state = m_pControl->GetAt(i); + fprintf(file, "%s%s,integer", i ? ",": "", state->GetName()); + } + fprintf(file,"),("); + m_pEntry->CodeExit(file); + m_pEntry->CodeEntry(file); + fprintf(file, ")"); + + fprintf(file, ")\n\n"); + + m_pProcedures->Code(file, "\n", "\n", "\n\n"); + + m_pEntry->Code(file); + + //fprintf(file, "code(obsoper,(%s))\n\n", GetName()); + + fprintf(file, "code(obsinstance_table,%d,`\n", L+1); + m_pEntry->CodeTable(file); + fprintf(file, "')\n\n"); + + fprintf(file, "code(end_obsinstance)\n\n"); +} diff --git a/src/model/entity.h b/src/model/entity.h new file mode 100644 index 0000000000000000000000000000000000000000..8c04a91b96fffeb3a3aea3f086ced149bf2eba1c --- /dev/null +++ b/src/model/entity.h @@ -0,0 +1,263 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract entity interface + * + */ + +class IfEntity : public IfObject { + + public: + IfEntity(IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags = 0); + virtual ~IfEntity(); + + public: + inline IfList<IfConstant>* GetConstants() const { return m_pConstants; } + inline IfList<IfType>* GetTypes() const { return m_pTypes; } + inline IfList<IfVariable>* GetVariables() const { return m_pVariables; } + inline IfList<IfProcedure>* GetProcedures() const { return m_pProcedures; } + + public: + virtual const char* GetClass() const + { return "entity"; } + virtual int IsEntity() const + { return 1; } + + virtual int IsSystem() const { return 0; } + virtual int IsProcess() const { return 0; } + virtual int IsObserver() const { return 0; } + virtual int IsPriority() const { return 0; } + + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + protected: + IfList<IfConstant>* m_pConstants; + IfList<IfType>* m_pTypes; + IfList<IfVariable>* m_pVariables; + IfList<IfProcedure>* m_pProcedures; + +}; + +/* + * + * system entity interface + * + */ + +class IfSystemEntity : public IfEntity { + + public: + IfSystemEntity(IfList<IfProcessEntity>* Processes, + IfList<IfPriorityRuleEntity>* PriorityRules, + IfList<IfObserverEntity>* Observers, + IfList<IfSignalroute>* Signalroutes, + IfList<IfSignal>* Signals, + IfList<IfResource>* Resources, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags = 0); + virtual ~IfSystemEntity(); + + public: + inline IfList<IfProcessEntity>* GetProcesses() const { return m_pProcesses; } + inline IfList<IfPriorityRuleEntity>* GetPriorityRules() const { return m_pPriorityRules; } + inline IfList<IfObserverEntity>* GetObservers() const { return m_pObservers; } + inline IfList<IfSignalroute>* GetSignalroutes() const { return m_pSignalroutes; } + inline IfList<IfSignal>* GetSignals() const { return m_pSignals; } + inline IfList<IfResource>* GetResources() const { return m_pResources; } + + public: + virtual int IsSystem() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual void CreateSigUnionType(); + + protected: + IfList<IfProcessEntity>* m_pProcesses; + IfList<IfPriorityRuleEntity>* m_pPriorityRules; + IfList<IfObserverEntity>* m_pObservers; + IfList<IfSignalroute>* m_pSignalroutes; + IfList<IfSignal>* m_pSignals; + IfList<IfResource>* m_pResources; + +}; + +/* + * + * automaton entity interface : abstract base for process and observer + * + */ + +class IfAutomatonEntity : public IfEntity { + + public: + IfAutomatonEntity(IfList<IfState>* States, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags = 0); + virtual ~IfAutomatonEntity(); + + public: + inline IfList<IfState>* GetStates() const { return m_pStates; } + inline IfState* GetEntry() const { return m_pEntry; } + inline IfList<IfState>* GetControl() const { return m_pControl; } + inline IfSystemEntity* GetSystem() const { return m_pSystem; } + + + protected: + IfList<IfState>* m_pStates; + + protected: + IfState* m_pEntry; + IfList<IfState>* m_pControl; + IfSystemEntity* m_pSystem; + +}; + + +/* + * + * process entity interface + * + */ + +class IfProcessEntity : public IfAutomatonEntity { + + public: + IfProcessEntity(IfConstant* Instances, + IfList<IfVariable>* Parameters, + IfList<IfState>* States, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags = 0); + virtual ~IfProcessEntity(); + + public: + inline IfConstant* GetInstances() const { return m_pInstances; } + inline IfList<IfVariable>* GetParameters() const { return m_pParameters; } + + inline IfList<IfSignalroute>* GetInRoutes() const { return m_pInRoutes; } + inline IfList<IfSignalroute>* GetOutRoutes() const { return m_pOutRoutes; } + inline IfList<IfSignal>* GetInSignals() const { return m_pInSignals; } + inline IfList<IfSignal>* GetOutSignals() const { return m_pOutSignals; } + inline IfList<IfSignal>* GetEnvSignals() const { return m_pEnvSignals; } + + //inline IfState* GetEntry() const { return m_pEntry; } + //inline IfSystemEntity* GetSystem() const { return m_pSystem; } + + virtual void Link(IfSignalroute* route); + + public: + virtual int IsProcess() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + protected: + IfConstant* m_pInstances; + IfList<IfVariable>* m_pParameters; + + protected: + //IfState* m_pEntry; + IfList<IfSignalroute>* m_pInRoutes; + IfList<IfSignalroute>* m_pOutRoutes; + IfList<IfSignal>* m_pInSignals; + IfList<IfSignal>* m_pOutSignals; + IfList<IfSignal>* m_pEnvSignals; + +}; + +/* + * + * observer entity interface + * + */ + +class IfObserverEntity : public IfAutomatonEntity { + + public: + enum EObsKind { + PURE = 1, + CUT = 2, + INTRUSIVE = 3, + }; + + public: + IfObserverEntity(EObsKind kind, + IfList<IfState>* States, + IfList<IfConstant>* Constants, + IfList<IfType>* Types, + IfList<IfVariable>* Variables, + IfList<IfProcedure>* Procedures, + char* Name, + unsigned Flags = 0); + virtual ~IfObserverEntity(); + + public: + virtual int IsObserver() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + virtual EObsKind getKind() const { return m_kind; } + + protected: + EObsKind m_kind; + +}; diff --git a/src/model/expression.C b/src/model/expression.C new file mode 100644 index 0000000000000000000000000000000000000000..e0f4559413b053ced2e7281852601f849c90e016 --- /dev/null +++ b/src/model/expression.C @@ -0,0 +1,1560 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of expressions + * + */ + +#include "model.h" + +IfExpression::IfExpression(unsigned Flags) + : IfObject(NULL, Flags) { + m_pType = NULL; +} + +int IfExpression::Match(const IfType* Type) { + int expect = + Type != NULL && + m_pType != NULL && + m_pType->Match(Type); + if (!expect) + Protest("type mismatch"); + return expect ? 1 : 0; +} + +void IfExpression::PostCompile() { + if (m_pType != NULL && m_pType->GetFlag(TIMED)) + SetFlag(TIMED, 1); + if (m_pType == NULL) + SetFlag(CORRECT, 0); + IfObject::PostCompile(); +} + +int IfExpression::Use(const IfVariable* Variable) const { + // pure virtual + return 0; +} + +int IfExpression::Def(const IfVariable* Variable) const { + // almost pure virtual + return 0; +} + +/* + * + * void expression + * + */ + +IfVoidExpression::IfVoidExpression(unsigned Flags) + : IfExpression(Flags) { +} + +void IfVoidExpression::Dump(FILE* file) const { + fprintf(file, "void"); +} + +int IfVoidExpression::Match(const IfType* Type) { + if (m_pType == NULL) + m_pType = (IfType*) Type; + return IfExpression::Match(Type); +} + +void IfVoidExpression::PostCompile() { + if (m_pType != NULL && m_pType->GetFlag(TIMED)) + SetFlag(TIMED, 1); + IfObject::PostCompile(); +} + +void IfVoidExpression::Code(FILE* file) const { +} + +int IfVoidExpression::Use(const IfVariable* Variable) const { + return 0; +} + +/* + * + * constant expression + * + */ + +IfConstantExpression::IfConstantExpression(IfConstant* Constant, + unsigned Flags) + : IfExpression(Flags) { + m_pConstant = Constant; +} + +IfConstantExpression::~IfConstantExpression() { + if (! m_pConstant->GetName()) delete m_pConstant; +} + +void IfConstantExpression::Dump(FILE* file) const { + m_pConstant->DumpNameOrValue(file); +} + +void IfConstantExpression::PreCompile() { + IfExpression::PreCompile(); + + if (!m_pConstant->GetName()) + m_pConstant->Compile(); + m_pType = m_pConstant->GetType(); +} + +void IfConstantExpression::Code(FILE* file) const { + m_pConstant->CodeNameOrValue(file); +} + +int IfConstantExpression::Use(const IfVariable* Variable) const { + return 0; +} + +/* + * + * variable expression + * + */ + +IfVariableExpression::IfVariableExpression(IfVariable* Variable, + unsigned Flags) + : IfExpression(Flags) { + m_pVariable = Variable; +} + +void IfVariableExpression::Dump(FILE* file) const { + fprintf(file, "%s", m_pVariable->GetName()); +} + +void IfVariableExpression::PreCompile() { + IfExpression::PreCompile(); + + m_pType = m_pVariable->GetType(); +} + +void IfVariableExpression::Code(FILE* file) const { + m_pVariable->Code(file); +} + +int IfVariableExpression::Use(const IfVariable* Variable) const { + return (m_pVariable == Variable) ? 1 : 0; +} + +int IfVariableExpression::Def(const IfVariable* Variable) const { + return (m_pVariable == Variable) ? 1 : 0; +} + +/* + * + * call expression + * + */ + +IfExpression::Operator +IfCallExpression::OPERATOR[] = { + { "", "", 0, -1}, // UNKNOWN + { "insert", "insert", 0, 3}, + { "remove", "remove", 0, 2}, + { "index", "index", 0, 2}, + { "obs_queue_length", "obs_queue_length", 0, 1}, + { "obs_queue_get_first", "obs_queue_get_first", 0, 1}, + { "obs_queue_get_last", "obs_queue_get_last", 0, 1}, + { "obs_queue_get_at", "obs_queue_get_at", 0, 2}, + { "obs_queue_remove_first", "obs_queue_remove_first", 0, 1}, + { "obs_queue_remove_last", "obs_queue_remove_last", 0, 1}, + { "obs_queue_remove_at", "obs_queue_remove_at", 0, 2}, + { NULL, NULL, 0, -1}, // CALL_END_PREDEF + { NULL, NULL, 0, -1}, // CONSTRUCTOR + { NULL, NULL, 0, -1} // FUNCTION +}; + +IfCallExpression::IfCallExpression(char* Name, + IfList<IfExpression>* Parameters, + unsigned Flags) + : IfExpression(Flags) { + m_eOperator = UNKNOWN; + m_pParameters = Parameters; + m_pName = Name; + + m_pFunction = NULL; +} + +IfCallExpression::~IfCallExpression() { + delete m_pParameters; + free(m_pName); +} + +void IfCallExpression::Dump(FILE* file) const { + fprintf(file, "%s(", m_pName); + m_pParameters->Dump(file, "", ", ", ""); + fprintf(file, ")"); +} + +void IfCallExpression::PreCompile() { + IfExpression::PreCompile(); + + int ok = 1, tm = 0; + int i; + + ok &= m_pParameters->Compile(); + + for(i = 0; i < m_pParameters->GetCount(); i++) + tm |= m_pParameters->GetAt(i)->IsTimed(); + SetFlag(TIMED, tm); + + ok &= !tm; + + if (!ok) return; + + /// try predef operator inference + + for(i = 0; OPERATOR[i].name; i++) + if (!strcmp(m_pName, OPERATOR[i].name)) { + m_eOperator = (EOperator) i; + break; + } + + if (IsPredef()) { + IfType* integer = TYPES[IfBasicType::INTEGER]; + IfType *t0 = NULL; + IfType *t1 = NULL; + IfType *t2 = NULL; + + if (OPERATOR[m_eOperator].arity != m_pParameters->GetCount()) + return; + if (OPERATOR[m_eOperator].arity >= 1) + t0 = m_pParameters->GetAt(0)->GetType(); + if (OPERATOR[m_eOperator].arity >= 2) + t1 = m_pParameters->GetAt(1)->GetType(); + if (OPERATOR[m_eOperator].arity >= 3) + t2 = m_pParameters->GetAt(2)->GetType(); + + switch (m_eOperator) { + case INSERT: + if (t0->IsString() && + t1->Match(integer) && + t2->Match(((IfStringType*) t0)->GetElement())) + m_pType = t0; + break; + case REMOVE: + if (t0->IsString() && + t1->Match(integer)) + m_pType = t0; + break; + case INDEX: + if (t0->IsString() && + t1->Match(((IfStringType*) t0)->GetElement())) + m_pType = integer; + break; + case OBS_QLENGTH: + if (CONTEXT.GetSize() < 2 || + (CONTEXT.GetSize() >= 2 && + !((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver() && + !((IfEntity*)(CONTEXT.GetAt(1)))->IsPriority())) { + Protest("expression only valid in observers and priority rules"); + break; + } + if (t0->Match(TYPES[IfBasicType::PID])) { + // bind ok + m_pType = integer; + } + break; + case OBS_QGETFIRST: + case OBS_QGETLAST: + case OBS_QGETAT: + case OBS_QREMOVEFIRST: + case OBS_QREMOVELAST: + case OBS_QREMOVEAT: + if (CONTEXT.GetSize() < 2 || + (CONTEXT.GetSize() >= 2 && + !((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver() && + !((IfEntity*)(CONTEXT.GetAt(1)))->IsPriority())) { + Protest("expression only valid in observers and priority rules"); + break; + } + if (t1 && !t1->Match(TYPES[IfBasicType::INTEGER]) ) { + // type error + break; + } + if (t0->Match(TYPES[IfBasicType::PID])) { + // bind ok + m_pType = ((IfEntity*)(CONTEXT.GetAt(0)))->GetTypes()->Find("t_if_signal"); + } + break; + default: + break; + } + } + + // try type constructor inference + if (m_eOperator == UNKNOWN) + for(int k = 1; k >= 0; k--) { + IfEntity* entity = (IfEntity*) CONTEXT[k]; + IfType* type = entity->GetTypes()->Find(m_pName); + if (type != NULL) { + m_eOperator = CONSTRUCTOR; + if (Match(type)) + m_pType = type; + else + Protest("type mismatch"); + break; + } + } + + // try abstract function inference + if (m_eOperator == UNKNOWN) + for(int k = 1; k >= 0; k--) { + IfEntity* entity = (IfEntity*) CONTEXT[k]; // process, then system + for(int j = 0; j < entity->GetTypes()->GetCount(); j++) { + IfType* type = entity->GetTypes()->GetAt(j); + if (type->IsAbstract()) { + IfAbstractType* abstract = (IfAbstractType*) type; + for(int i = 0; i < abstract->GetFunctions()->GetCount(); i++) { + IfFunction* function = abstract->GetFunctions()->GetAt(i); + if (MatchFunc(function)) { + if (m_pType == NULL) { + m_eOperator = FUNCTION; + m_pFunction = function; + m_pType = function->GetResult(); + } + else + Protest("ambiguous call [abstract]"); + } + } + } + } + } +} + +int IfCallExpression::Match(const IfType* type) { + int match = 0; + + if (type->IsString()) { + IfStringType* string = (IfStringType*) type; + if (m_pParameters->GetCount() == 0) + match = 1; + if (m_pParameters->GetCount() == 1) { + IfType* ptype = m_pParameters->GetAt(0)->GetType(); + IfType* etype = string->GetElement(); + match = ptype->Match(etype); + } + } + + if (type->IsRecord()) { + IfRecordType* record = (IfRecordType*) type; + match = m_pParameters->GetCount() == record->GetFields()->GetCount(); + for(int i = 0; i < m_pParameters->GetCount() && match; i++) { + IfType* ptype = m_pParameters->GetAt(i)->GetType(); + IfType* ftype = record->GetFields()->GetAt(i)->GetType(); + match &= ptype->Match(ftype); + } + } + + return match; +} + +int IfCallExpression::MatchFunc(const IfFunction* function) { + int match = + m_pParameters->GetCount() == function->GetParameters()->GetCount(); + for(int i = 0; i < m_pParameters->GetCount() && match; i++) { + IfType* ptype = m_pParameters->GetAt(i)->GetType(); + IfType* ftype = function->GetParameters()->GetAt(i); + match &= ptype->Match(ftype); + } + match &= strcmp(m_pName, function->GetName()) == 0; + return match; +} + +void IfCallExpression::Code(FILE* file) const { + if (IsPredef()) { + IfType* type = m_pParameters->GetAt(0)->GetType(); + if(OBS_QLENGTH <= m_eOperator && m_eOperator <= OBS_QREMOVEAT) { + if(CONTEXT.GetCount()>0) // we are in a priority rule (the only place where we do CONTEXT.Push before Code ! + fprintf(file, "::if_%s_%s(q,", + type->GetName(), OPERATOR[m_eOperator].code); + else + fprintf(file, "if_%s_%s(", + type->GetName(), OPERATOR[m_eOperator].code); + } + } + if (IsConstructor()) { + fprintf(file, "if_%s_make(", m_pType->GetName()); + } + if (IsFunction()) { + fprintf(file, "function_name(%s)(", m_pFunction->GetName()); + } + m_pParameters->Code(file, "", ",", ""); + fprintf(file, ")"); +} + +int IfCallExpression::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pParameters->GetCount() && !use; i++) + use |= m_pParameters->GetAt(i)->Use(Variable); + return use; +} + +/* + * + * field expression + * + */ + +IfFieldExpression::IfFieldExpression(IfExpression* Base, + char* FieldName, + unsigned Flags) + : IfExpression(Flags) { + m_eKind = NONE; + m_pBase = Base; + m_pFieldName = FieldName; + m_pField = NULL; +} + +IfFieldExpression::~IfFieldExpression() { + delete m_pBase; + free(m_pFieldName); +} + + +void IfFieldExpression::Dump(FILE* file) const { + m_pBase->Dump(file); + fprintf(file, ".%s", m_pField ? m_pField->GetName() : m_pFieldName); +} + +void IfFieldExpression::PreCompile() { + IfExpression::PreCompile(); + + m_pBase->Compile(); + + if (m_pBase->GetType() == NULL) + return; + + if (m_pBase->GetType()->IsRecord() || m_pBase->GetType()->IsUnion()) { + IfRecordType* record = (IfRecordType*) m_pBase->GetType(); + m_pField = record->GetFields()->Find(m_pFieldName); + m_eKind = RECORD; + } + + if (m_pBase->IsCast()) { + IfCastExpression* cast = (IfCastExpression*) m_pBase; + if (cast->IsProcess()) { + IfAutomatonEntity* process = (IfAutomatonEntity*) cast->GetCast(); + m_pField = process->GetVariables()->Find(m_pFieldName); + if(!m_pField && process->IsProcess()) m_pField = ((IfProcessEntity*)process)->GetParameters()->Find(m_pFieldName); + m_eKind = PROCESS; + + if (m_pField) + m_pField->SetFlag(IfVariable::IMPORTED, 1); + + if (m_pField && !m_pField->IsPublic() + && (CONTEXT.GetSize() < 2 || + (CONTEXT.GetSize() >= 2 && + (!((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver() || + ((IfObserverEntity*)(CONTEXT.GetAt(1)))->getKind() < IfObserverEntity::INTRUSIVE)))) { + // SetFlag(CORRECT, 0); + Protest("private member access"); + } + } + } + + if (m_pField) + m_pType = m_pField->GetType(); +} + +void IfFieldExpression::Code(FILE* file) const { + IfCastExpression* cast = NULL; + switch (m_eKind) { + case RECORD: + if(m_pBase->GetType()->IsSigUnion()) { + fprintf(file, "(((message_name(%s)*)(", m_pField->GetName()); + m_pBase->Code(file); + fprintf(file, "))->m_par)"); + } else { + m_pBase->Code(file); + fprintf(file, ".%s", m_pField->GetName()); + } + break; + case PROCESS: + cast = (IfCastExpression*) m_pBase; + fprintf(file, "imp0rt(%s,", cast->GetCast()->GetName()); + m_pBase->Code(file); + fprintf(file, ",%s)", m_pField->GetName()); + break; + default: + break; + } +} + +int IfFieldExpression::Use(const IfVariable* Variable) const { + return m_pBase->Use(Variable) || (m_pField == Variable); +} + +int IfFieldExpression::Def(const IfVariable* Variable) const { + return m_pBase->Def(Variable) || (m_pField == Variable); +} + +/* + * + * instate expression + * + */ + +IfInstateExpression::IfInstateExpression(IfExpression* Process, + char* StateName, + unsigned Flags) + : IfExpression(Flags) { + m_pProcess = Process; + m_pStateName = StateName; + m_pState = NULL; +} + +IfInstateExpression::~IfInstateExpression() { + delete m_pProcess; + free(m_pStateName); +} + + +void IfInstateExpression::Dump(FILE* file) const { + m_pProcess->Dump(file); + fprintf(file, " instate %s", m_pState ? m_pState->GetName() : m_pStateName); +} + +void IfInstateExpression::PreCompile() { + IfExpression::PreCompile(); + + /*if( CONTEXT.GetSize() < 2 || CONTEXT.GetSize() >= 2 && !((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver()) { + Protest("expression only valid in observers or priority rules"); + return; + }*/ + + m_pProcess->Compile(); + + if (m_pProcess->GetType() == NULL) + return; + + if (m_pProcess->IsCast()) { + IfCastExpression* cast = (IfCastExpression*) m_pProcess; + if (cast->IsProcess()) { + IfProcessEntity* process = (IfProcessEntity*) cast->GetCast(); + m_pState = process->GetEntry()->Find(m_pStateName); + } + } + + if (m_pState) + m_pType = TYPES[IfBasicType::BOOLEAN]; +} + +void IfInstateExpression::_Code(FILE* file, char* procName, IfExpression* process, IfState* rootState) const { + // recursive version, for testing sub-states + if( rootState->GetStates() == NULL || rootState->GetStates()->GetCount() == 0 ) { + fprintf(file, "(getStateNo(%s,", procName); + process->Code(file); + fprintf(file, ") == %d)", rootState->GetIndex()); + } else { + fprintf(file, "((getStateNo(%s,", procName); + process->Code(file); + fprintf(file, ") == %d) ", rootState->GetIndex()); + for( int i=0; i<rootState->GetStates()->GetCount(); i++ ) { + fprintf(file, " || "); + _Code(file, procName, process, rootState->GetStates()->GetAt(i)); + } + fprintf(file, ")"); + } +} + +void IfInstateExpression::Code(FILE* file) const { + IfCastExpression* cast = (IfCastExpression*)m_pProcess; + _Code(file, cast->GetCast()->GetName(), m_pProcess, m_pState); +/* fprintf(file, "(getStateNo(%s,", cast->GetCast()->GetName()); + m_pProcess->Code(file); + fprintf(file, ") == %d)", m_pState->GetIndex());*/ +} + +/* + * + * instanceof expression + * + */ + +IfInstanceofExpression::IfInstanceofExpression(IfExpression* term, + char* name, + unsigned Flags) + : IfExpression(Flags) { + m_pTerm = term; + m_pName = name; + m_pSig = NULL; + m_pProc = NULL; +} + +IfInstanceofExpression::~IfInstanceofExpression() { + if(m_pTerm) delete m_pTerm; + if(m_pName) free(m_pName); +} + +void IfInstanceofExpression::Dump(FILE* file) const { + m_pTerm->Dump(file); + fprintf(file, " instanceof "); + if( m_pTerm->GetType() == TYPES[IfBasicType::PID] ) { + if( m_pProc ) fprintf(file, "%s", m_pProc->GetName()); + else fprintf(file, "%s", m_pName); + } else { + if( m_pSig ) fprintf(file, "%s", m_pSig->GetName()); + else fprintf(file, "%s", m_pName); + } +} + +void IfInstanceofExpression::PreCompile() { + IfExpression::PreCompile(); + +/* if( CONTEXT.GetSize() < 2 || CONTEXT.GetSize() >= 2 && !((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver() ) { + Protest("expression only valid in observers"); + return; + }*/ + + m_pTerm->Compile(); + + if (m_pTerm->GetType() == TYPES[IfBasicType::PID]) { + if(m_pName) { + m_pProc = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetProcesses()->Find(m_pName); + if( !m_pProc ) return; + } + } else if (m_pTerm->GetType() == ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal") ) { + if(m_pName) { + m_pSig = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetSignals()->Find(m_pName); + if( !m_pSig ) return; + } + } else + return; + + m_pType = TYPES[IfBasicType::BOOLEAN]; +} + +void IfInstanceofExpression::Code(FILE* file) const { + if (m_pTerm->GetType() == TYPES[IfBasicType::PID]) { + if(m_pProc) { + fprintf(file, "(process_name(%s) == if_pid_proc(", m_pProc->GetName()); + m_pTerm->Code(file); + fprintf(file, "))"); + } else { + fprintf(file, "(if_pid_nil != ("); + m_pTerm->Code(file); + fprintf(file, "))"); + } + } else { //if (m_pTerm->GetType() == ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal") ) + if(m_pSig) { + fprintf(file, "("); + m_pTerm->Code(file); + fprintf(file, "!= NULL && "); + fprintf(file, "(signal_name(%s) == ", m_pSig->GetName()); + m_pTerm->Code(file); + fprintf(file, "->getSid())"); + fprintf(file, ")"); + } else { + fprintf(file, "(NULL != "); + m_pTerm->Code(file); + fprintf(file, ")"); + } + } +} + +/* + * + * eventobs expression + * + */ + +IfEventObsExpression::IfEventObsExpression(EEvtKind k, + char* name, + IfExpression* term1, + IfExpression* term2, + IfExpression* term3, + IfExpression* term4, + unsigned Flags) + : IfExpression(Flags) { + m_kind = k; + m_pTerm1 = term1; + m_pTerm2 = term2; + m_pTerm3 = term3; + m_pTerm4 = term4; + m_pName = name; + m_pSig = NULL; + m_pProcess = NULL; +} + +IfEventObsExpression::~IfEventObsExpression() { + if(m_pTerm1) delete m_pTerm1; + if(m_pTerm2) delete m_pTerm2; + if(m_pTerm3) delete m_pTerm3; + if(m_pTerm4) delete m_pTerm4; + free(m_pName); +} + + +void IfEventObsExpression::Dump(FILE* file) const { + switch(m_kind) { + case INPUT: + fprintf(file, "obsinput %s ", m_pSig ? m_pSig->GetName() : m_pName); + if( m_pTerm1 ) { + fprintf(file, "in "); + m_pTerm1->Dump(file); + } + break; + case DISCARD: + fprintf(file, "obsdiscard %s ", m_pSig ? m_pSig->GetName() : m_pName); + if( m_pTerm1 ) { + fprintf(file, "in "); + m_pTerm1->Dump(file); + } + break; + case OUTPUT: + fprintf(file, "obsoutput %s ", m_pSig ? m_pSig->GetName() : m_pName); + if( m_pTerm1 ) { + fprintf(file, " [ "); + m_pTerm1->Dump(file); + fprintf(file, " ] "); + } + if( m_pTerm2 ) { + fprintf(file, " from "); + m_pTerm2->Dump(file); + } + if( m_pTerm3 ) { + fprintf(file, " via "); + m_pTerm3->Dump(file); + } + if( m_pTerm4 ) { + fprintf(file, " to "); + m_pTerm4->Dump(file); + } + break; + case FORK: + fprintf(file, "obsfork %s ", m_pProcess ? m_pProcess->GetName() : (m_pName ? m_pName : "") ); + if( m_pTerm1 ) { + fprintf(file, "in "); + m_pTerm1->Dump(file); + } + break; + case KILL: + if(m_pName) + fprintf(file, "obskillprocess %s ", m_pProcess ? m_pProcess->GetName() : m_pName); + else if(m_pTerm1) { + fprintf(file, "obskillpid "); + m_pTerm1->Dump(file); + } else { + fprintf(file, "obskillpid "); /*!!! not accepted by yacc yet */ + } + if( m_pTerm2 ) { + fprintf(file, "in "); + m_pTerm2->Dump(file); + } + break; + case DELIVER: + case INFORMAL: + case PROBABILITY: + // no concrete syntax for the moment + fprintf(file, "true"); + break; + } +} + +void IfEventObsExpression::PreCompile() { + IfExpression::PreCompile(); + + if (CONTEXT.GetSize() < 2 || + (CONTEXT.GetSize() >= 2 && !((IfEntity*)(CONTEXT.GetAt(1)))->IsObserver())) { + Protest("expression only valid in observers"); + return; + } + + switch(m_kind) { + case INPUT: + case DISCARD: + if ( m_pTerm1 ) { + m_pTerm1->Compile(); + if (m_pTerm1->GetType() != TYPES[IfBasicType::PID] ) + return; + } + if( m_pName) { + m_pSig = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetSignals()->Find(m_pName); + if( !m_pSig ) return; + m_pSig->SetFlag(IfSignal::OBSERVED, true); + } + m_pType = ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal"); + + break; + case OUTPUT: + if ( m_pTerm1 ) { + m_pTerm1->Compile(); + if (m_pTerm1->GetType() != TYPES[IfBasicType::INTEGER] ) + return; + } + if ( m_pTerm2 ) { + m_pTerm2->Compile(); + if (m_pTerm2->GetType() != TYPES[IfBasicType::PID] ) + return; + } + if ( m_pTerm3 ) { + m_pTerm3->Compile(); + if (m_pTerm3->GetType() != TYPES[IfBasicType::PID] ) + return; + } + if ( m_pTerm4 ) { + m_pTerm4->Compile(); + if (m_pTerm4->GetType() != TYPES[IfBasicType::PID] ) + return; + } + if( m_pName) { + m_pSig = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetSignals()->Find(m_pName); + if( !m_pSig ) return; + m_pSig->SetFlag(IfSignal::OBSERVED, true); + } + m_pType = ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal"); + + break; + case FORK: + if ( m_pTerm1 ) { + m_pTerm1->Compile(); + if (m_pTerm1->GetType() != TYPES[IfBasicType::PID] ) + return; + } + if( m_pName ) { + m_pProcess = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetProcesses()->Find(m_pName); + if( !m_pProcess ) return; + } + m_pType = TYPES[IfBasicType::BOOLEAN]; + + break; + case KILL: + if( m_pName ) { + m_pProcess = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetProcesses()->Find(m_pName); + if( !m_pProcess ) return; + } else if ( m_pTerm1 ) { + m_pTerm1->Compile(); + if (m_pTerm1->GetType() != TYPES[IfBasicType::PID] ) + return; + } + if ( m_pTerm2 ) { + m_pTerm2->Compile(); + if (m_pTerm2->GetType() != TYPES[IfBasicType::PID] ) + return; + } + m_pType = TYPES[IfBasicType::BOOLEAN]; + + break; + case DELIVER: + if ( m_pTerm1 ) { + m_pTerm1->Compile(); + if (m_pTerm1->GetType() != TYPES[IfBasicType::PID] ) + return; + } + if( m_pName) { + m_pSig = ((IfSystemEntity*)CONTEXT.GetAt(0))->GetSignals()->Find(m_pName); + if( !m_pSig ) return; + } + m_pType = ((IfEntity*)CONTEXT.GetAt(0))->GetTypes()->Find("t_if_signal"); + + break; + case INFORMAL: + if ( m_pTerm1 ) { + m_pTerm1->Compile(); + if (m_pTerm1->GetType() != TYPES[IfBasicType::PID] ) + return; + } + m_pType = TYPES[IfBasicType::BOOLEAN]; + + break; + case PROBABILITY: + m_pType = TYPES[IfBasicType::BOOLEAN]; + + break; + } +} + +void IfEventObsExpression::Code(FILE* file) const { + switch(m_kind) { + case INPUT: + case DISCARD: + if(m_kind == INPUT) fprintf(file, "(if_obs_input("); + else fprintf(file, "(if_obs_discard("); + if(m_pSig) fprintf(file, "signal_name(%s)", m_pSig->GetName()); + else fprintf(file, "(unsigned)-1"); + fprintf(file, ", "); + if ( m_pTerm1 ) m_pTerm1->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, "))"); + + break; + case OUTPUT: + fprintf(file, "(if_obs_output("); + if(m_pSig) fprintf(file, "signal_name(%s)", m_pSig->GetName()); + else fprintf(file, "(unsigned)-1"); + fprintf(file, ", "); + + if ( m_pTerm1 ) m_pTerm1->Code(file); + else fprintf(file, "0"); + fprintf(file, ", "); + + if ( m_pTerm2 ) m_pTerm2->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, ", "); + + if ( m_pTerm3 ) m_pTerm3->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, ", "); + + if ( m_pTerm4 ) m_pTerm4->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, "))"); + + break; + case FORK: + fprintf(file, "(if_obs_fork("); + if( m_pProcess ) fprintf(file, "process_name(%s), ", m_pProcess->GetName()); + else fprintf(file, "(unsigned)-1, "); + if ( m_pTerm1 ) m_pTerm1->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, "))"); + + break; + case KILL: + fprintf(file, "(if_obs_kill("); + if( m_pName ) fprintf(file, "process_name(%s),", m_pProcess->GetName()); + else fprintf(file, "(unsigned)-1,"); + if( m_pTerm1 ) m_pTerm1->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, ","); + if( m_pTerm2 ) m_pTerm2->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, "))"); + + break; + case DELIVER: + fprintf(file, "(if_obs_deliver("); + if(m_pSig) fprintf(file, "signal_name(%s)", m_pSig->GetName()); + else fprintf(file, "(unsigned)-1"); + fprintf(file, ", "); + if ( m_pTerm1 ) m_pTerm1->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, "))"); + + break; + case INFORMAL: + fprintf(file, "(if_obs_informal(%s,", m_pName); + if( m_pTerm1 ) m_pTerm1->Code(file); + else fprintf(file, "(unsigned)-1"); + fprintf(file, "))"); + + break; + case PROBABILITY: + fprintf(file, "(if_obs_probability())"); + + break; + } +} + +/* + * + * index expression + * + */ + +IfIndexExpression::IfIndexExpression(IfExpression* Base, + IfExpression* Index, + unsigned Flags) + : IfExpression(Flags) { + m_pBase = Base; + m_pIndex = Index; +} + +IfIndexExpression::~IfIndexExpression() { + delete m_pBase; + delete m_pIndex; +} + +void IfIndexExpression::Dump(FILE* file) const { + m_pBase->Dump(file); + fprintf(file, "["); + m_pIndex->Dump(file); + fprintf(file, "]"); +} + +void IfIndexExpression::PreCompile() { + IfExpression::PreCompile(); + + m_pBase->Compile(); + m_pIndex->Compile(); + + if (m_pBase->GetType() && m_pIndex->GetType()) { + IfType* integer = TYPES[IfBasicType::INTEGER]; + + if (m_pBase->GetType()->IsArray() && + m_pIndex->GetType()->Match(integer)) + m_pType = ((IfArrayType*) m_pBase->GetType())->GetElement(); + + if (m_pBase->GetType()->IsString() && + m_pIndex->GetType()->Match(integer)) + m_pType = ((IfStringType*) m_pBase->GetType())->GetElement(); + + if (m_pBase->GetType()->IsTree() && + m_pIndex->GetType()->IsString() && + ((IfStringType*) m_pIndex->GetType())->GetElement()->Match(integer)) + m_pType = ((IfTreeType*) m_pBase->GetType())->GetElement(); + } + + if (m_pIndex->IsTimed()) { + SetFlag(TIMED, 1); + SetFlag(CORRECT, 0); + } +} + +void IfIndexExpression::Code(FILE* file) const { + m_pBase->Code(file); + fprintf(file, "["); + m_pIndex->Code(file); + fprintf(file, "]"); +} + +int IfIndexExpression::Use(const IfVariable* Variable) const { + return m_pBase->Use(Variable) || m_pIndex->Use(Variable); +} + +int IfIndexExpression::Def(const IfVariable* Variable) const { + return m_pBase->Def(Variable); +} + +/* + * + * unary expression + * + */ + +IfExpression::Operator +IfUnaryExpression::OPERATOR[] = { + {"active","active", 0, 1}, + {"timeval","timeval", 0, 1}, + {"length","length", 0, 1}, + { "+", "uplus", 0, 1}, + { "-","uminus", 0, 1}, + { "not", "not", 0, 1} +}; + + +IfUnaryExpression::IfUnaryExpression(EOperator Operator, + IfExpression* Right, + unsigned Flags) + : IfExpression(Flags) { + m_eOperator = Operator; + m_pRight = Right; +} + +IfUnaryExpression::~IfUnaryExpression() { + delete m_pRight; +} + +void IfUnaryExpression::Dump(FILE* file) const { + fprintf(file, "%s ", OPERATOR[m_eOperator].name); + m_pRight->Dump(file); +} + +void IfUnaryExpression::PreCompile() { + IfExpression::PreCompile(); + + IfType* boolean = TYPES[IfBasicType::BOOLEAN]; + IfType* integer = TYPES[IfBasicType::INTEGER]; + IfType* real = TYPES[IfBasicType::REAL]; + IfType* clock = TYPES[IfBasicType::CLOCK]; + IfType* tr = NULL; + + m_pRight->Compile(); + tr = m_pRight->GetType(); + + /// type inference + + if (tr) + switch (m_eOperator) { + case ACTIVE: case TIMEVAL: + if (tr->Match(clock) && m_pRight->IsReference()) + m_pType = (m_eOperator == ACTIVE) ? boolean : integer; + break; + case LENGTH: + if (tr->IsString()) + m_pType = integer; + break; + case PLUS: case MINUS: + if (tr->Match(integer)) + m_pType = integer; + if (tr->Match(real)) + m_pType = real; + break; + case NOT: + if (tr->Match(boolean)) + m_pType = boolean; + break; + } + + /// time inference + + if (m_pRight->IsTimed()) + if (m_eOperator != ACTIVE && m_eOperator != TIMEVAL) { + SetFlag(TIMED, 1); + SetFlag(CORRECT, 0); + } +} + +void IfUnaryExpression::Code(FILE* file) const { + IfType* type = NULL; + + switch (m_eOperator) { + case ACTIVE: case TIMEVAL: type = TYPES[IfBasicType::CLOCK]; break; + case LENGTH: type = m_pRight->GetType(); break; + case PLUS: case MINUS: type = m_pType; break; + case NOT: type = TYPES[IfBasicType::BOOLEAN]; break; + } + + fprintf(file, "unop(%s,%s)", OPERATOR[m_eOperator].code, type->GetName()); + + fprintf(file, "("); + m_pRight->Code(file); + fprintf(file, ")"); +} + +int IfUnaryExpression::Use(const IfVariable* Variable) const { + return m_pRight->Use(Variable); +} + +/* + * + * binary expression + * + */ + +IfExpression::Operator +IfBinaryExpression::OPERATOR[] = { + { "*", "mult", 1, 2}, + { "/", "div", 1, 2}, + { "%", "mod", 1, 2}, + { "+", "plus", 2, 2}, + { "-", "minus", 2, 2}, + { "^","concat", 2, 2}, + { "<", "lt", 3, 2}, + { "<=", "le", 3, 2}, + { ">=", "ge", 3, 2}, + { ">", "gt", 3, 2}, + { "=", "eq", 4, 2}, + { "<>", "ne", 4, 2}, + {"and", "and", 5, 2}, + { "or", "or", 6, 2} +}; + +IfBinaryExpression::IfBinaryExpression(IfExpression* Left, + EOperator Operator, + IfExpression* Right, + unsigned Flags) + : IfExpression(Flags) { + m_pLeft = Left; + m_eOperator = Operator; + m_pRight = Right; +} + +IfBinaryExpression::~IfBinaryExpression() { + delete m_pLeft; + delete m_pRight; +} + +void IfBinaryExpression::Dump(FILE* file) const { + fprintf(file, "("); + m_pLeft->Dump(file); + fprintf(file, " %s ", OPERATOR[m_eOperator].name); + m_pRight->Dump(file); + fprintf(file, ")"); +} + +void IfBinaryExpression::PreCompile() { + IfExpression::PreCompile(); + + IfType* boolean = TYPES[IfBasicType::BOOLEAN]; + IfType* integer = TYPES[IfBasicType::INTEGER]; + IfType* real = TYPES[IfBasicType::REAL]; + IfType* pid = TYPES[IfBasicType::PID]; + + IfType* tl = NULL; + IfType* tr = NULL; + + m_pLeft->Compile(); + m_pRight->Compile(); + tl = m_pLeft->GetType(); + tr = m_pRight->GetType(); + + /// type inference + + if (tl && tr) + switch (m_eOperator) { + case MULT: case DIV: case PLUS: case MINUS: + if (tl->Match(integer, real) && + tr->Match(integer, real)) { + if (tl->Match(real) || tr->Match(real)) + m_pType = real; + else + m_pType = integer; + } + break; + case MOD: + if (tl->Match(integer) && + tr->Match(integer)) + m_pType = integer; + break; + case CONCAT: + if (tl->IsString() && + tr == tl) + m_pType = tl; + break; + case LT: case LE: case GE: case GT: + if (tl->Match(integer, real, pid) && + tr->Match(integer, real, pid)) + m_pType = boolean; + break; + case EQ: case NE: + if ((tl->Match(integer, real) && + tr->Match(integer, real)) || + tl->GetBase() == tr->GetBase()) + m_pType = boolean; + break; + case AND: case OR: + if (tl->Match(boolean) && + tr->Match(boolean)) + m_pType = boolean; + break; + } + + /// time inference + + if (m_pLeft->IsTimed() || m_pRight->IsTimed()) { + SetFlag(TIMED, 1); + SetFlag(CORRECT, 0); + } + +} + +void IfBinaryExpression::Code(FILE* file) const { + IfType* integer = TYPES[IfBasicType::INTEGER]; + IfType* real = TYPES[IfBasicType::REAL]; + IfType* pid = TYPES[IfBasicType::PID]; + IfType* tl = m_pLeft->GetType(); + IfType* tr = m_pRight->GetType(); + + IfType* type = NULL; + + switch (m_eOperator) { + case EQ: case NE: + if (tl->Match(tr)) + type = tl->GetBase(); // no break + case LT: case LE: case GE: case GT: + if (tl->Match(real) || tr->Match(real)) + type = real; + else if (tl->Match(integer) || tr->Match(integer) || tl->Match(pid) || tr->Match(pid)) + type = integer; + break; + default: + type = m_pType; + } + + fprintf(file, "binop(%s,%s)", OPERATOR[m_eOperator].code, + type->GetName()); + + fprintf(file, "("); + m_pLeft->Code(file); + fprintf(file, ","); + m_pRight->Code(file); + fprintf(file, ")"); +} + +int IfBinaryExpression::Use(const IfVariable* Variable) const { + return m_pLeft->Use(Variable) || m_pRight->Use(Variable); +} + +/* + * + * conditional expression + * + */ + +IfTernaryExpression::IfTernaryExpression(EOperator Operator, + IfExpression* Top, + IfExpression* Left, + IfExpression* Right, + unsigned Flags) + : IfExpression(Flags) { + m_eOperator = Operator; + m_pTop = Top; + m_pLeft = Left; + m_pRight = Right; +} + +IfTernaryExpression::~IfTernaryExpression() { + delete m_pTop; + delete m_pLeft; + delete m_pRight; +} + +void IfTernaryExpression::Dump(FILE* file) const { + switch (m_eOperator) { + case CONDITIONAL: + fprintf(file, "("); + m_pTop->Dump(file); + fprintf(file, "?"); + m_pLeft->Dump(file); + fprintf(file, ":"); + m_pRight->Dump(file); + fprintf(file, ")"); + break; + case SUBSTRING: + m_pTop->Dump(file); + fprintf(file, "["); + m_pLeft->Dump(file); + fprintf(file, ":"); + m_pRight->Dump(file); + fprintf(file, "]"); + break; + } + +} + +void IfTernaryExpression::PreCompile() { + IfExpression::PreCompile(); + + IfType* boolean = TYPES[IfBasicType::BOOLEAN]; + IfType* integer = TYPES[IfBasicType::INTEGER]; + + m_pTop->Compile(); + m_pLeft->Compile(); + m_pRight->Compile(); + + if (m_pTop->GetType() && + m_pLeft->GetType() && + m_pRight->GetType()) + switch (m_eOperator) { + case CONDITIONAL: + if (m_pTop->GetType()->Match(boolean) && + m_pLeft->GetType() == m_pRight->GetType()) + m_pType = m_pLeft->GetType(); + break; + case SUBSTRING: + if (m_pTop->GetType()->IsString() && + m_pLeft->GetType()->Match(integer) && + m_pRight->GetType()->Match(integer)) + m_pType = m_pTop->GetType(); + break; + }; + + if (m_pTop->IsTimed() || + m_pLeft->IsTimed() || + m_pRight->IsTimed()) { + SetFlag(TIMED, 1); + SetFlag(CORRECT, 0); + } + +} + +void IfTernaryExpression::Code(FILE* file) const { + switch (m_eOperator) { + case CONDITIONAL: + fprintf(file, "("); + m_pTop->Code(file); + fprintf(file, "?"); + m_pLeft->Code(file); + fprintf(file, ":"); + m_pRight->Code(file); + fprintf(file, ")"); + break; + case SUBSTRING: + fprintf(file, "if_%s_substring", + m_pTop->GetType()->GetName()); + fprintf(file, "("); + m_pTop->Code(file); + fprintf(file, ","); + m_pLeft->Code(file); + fprintf(file, ","); + m_pRight->Code(file); + fprintf(file, ")"); + break; + } +} + +int IfTernaryExpression::Use(const IfVariable* Variable) const { + return + m_pTop->Use(Variable) || + m_pLeft->Use(Variable) || + m_pRight->Use(Variable); +} + +/* + * + * cast expressions + * + */ + +IfCastExpression::IfCastExpression(EKind Kind, + IfObject* Cast, + IfExpression* Right) { + m_eKind = Kind; + m_pCast = Cast; + m_pRight = Right; + m_pName = NULL; +} + +IfCastExpression::IfCastExpression(EKind Kind, + char* Name, + IfExpression* Right) { + m_eKind = Kind; + m_pCast = NULL; + m_pRight = Right; + m_pName = Name; +} + +IfCastExpression::~IfCastExpression() { + delete m_pRight; + if (m_pName) free(m_pName); +} + +void IfCastExpression::Dump(FILE* file) const { + fprintf(file, "({%s}", m_pCast ? m_pCast->GetName() : m_pName); + m_pRight->Dump(file); + fprintf(file, ")"); +} + +void IfCastExpression::PreCompile() { + IfExpression::PreCompile(); + + IfType* integer = TYPES[IfBasicType::INTEGER]; + IfType* pid = TYPES[IfBasicType::PID]; + IfType* clock = TYPES[IfBasicType::CLOCK]; + IfType* tr = NULL; + + // cast inference + + if (m_pCast == NULL) { + IfSystemEntity* sys = (IfSystemEntity*) CONTEXT[0]; + IfProcessEntity* proc = (IfProcessEntity*) CONTEXT[1]; + + switch (m_eKind) { + case TYPE: + if (m_pCast == NULL) + m_pCast = proc->GetTypes()->Find(m_pName); + if (m_pCast == NULL) + m_pCast = sys->GetTypes()->Find(m_pName); + if (m_pCast == NULL) + m_pCast = TYPES.Find(m_pName); + break; + case PROCESS: + if (m_pCast == NULL) + m_pCast = sys->GetProcesses()->Find(m_pName); + if (m_pCast == NULL) + m_pCast = sys->GetObservers()->Find(m_pName); + break; + case ROUTE: + if (m_pCast == NULL) + m_pCast = sys->GetSignalroutes()->Find(m_pName); + break; + } + } + + if (m_pCast == NULL) { + SetFlag(CORRECT, 0); + Protest("undefined name"); + } + + // type inference + + m_pRight->Compile(); + tr = m_pRight->GetType(); + + if (m_pCast && tr) + switch (m_eKind) { + case TYPE: + if (m_pCast == integer) + if (tr->IsScalar() && !tr->Match(clock)) + m_pType = integer; + break; + case PROCESS: + case ROUTE: + if (tr->Match(integer) || tr->Match(pid)) + m_pType = pid; + break; + } + + // time inference + + if (m_pRight->IsTimed()) { + SetFlag(TIMED, 1); + SetFlag(CORRECT, 0); + } + +} + +void IfCastExpression::Code(FILE* file) const { + IfType* pid = TYPES[IfBasicType::PID]; + IfType* tr = m_pRight->GetType(); + + switch (m_eKind) { + case TYPE: + fprintf(file, "(type_name(%s))", + m_pCast->GetName()); break; + case PROCESS: + case ROUTE: + fprintf(file, "if_pid_mk(%s_name(%s),", + m_eKind == PROCESS ? + (((IfAutomatonEntity*)m_pCast)->IsProcess() ? "process" : "observer") + : + "route", + m_pCast->GetName()); break; + } + + if (tr->Match(pid)) fprintf(file, "if_pid_idet("); + m_pRight->Code(file); + if (tr->Match(pid)) fprintf(file, ")"); + + if (m_eKind == PROCESS || m_eKind == ROUTE) + fprintf(file, ")"); +} + +int IfCastExpression::Use(const IfVariable* Variable) const { + return m_pRight->Use(Variable); +} + diff --git a/src/model/expression.h b/src/model/expression.h new file mode 100644 index 0000000000000000000000000000000000000000..04c83056173988158ea0e9d3dc8cc546d196e506 --- /dev/null +++ b/src/model/expression.h @@ -0,0 +1,636 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract expression interface + * + */ + +class IfExpression : public IfObject { + + public: + IfExpression(unsigned Flags = 0); + virtual ~IfExpression() {} + + public: + inline int IsTimed() const + { return GetFlag(TIMED); } + inline IfType* GetType() const + { return m_pType; } + + public: + virtual int IsReference() const { return 0; } + virtual int Match(const IfType*); + + public: + virtual const char* GetClass() const + { return "expression"; } + virtual int IsExpression() const + { return 1; } + + virtual int IsVoid() const { return 0; } + virtual int IsConstant() const { return 0; } + virtual int IsVariable() const { return 0; } + virtual int IsCall() const { return 0; } + virtual int IsField() const { return 0; } + virtual int IsInstate() const { return 0; } + virtual int IsInstanceof() const { return 0; } + virtual int IsEventObs() const { return 0; } + virtual int IsIndex() const { return 0; } + virtual int IsUnary() const { return 0; } + virtual int IsBinary() const { return 0; } + virtual int IsTernary() const { return 0; } + virtual int IsCast() const { return 0; } + + virtual void PostCompile(); + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + public: + struct Operator { + const char* name; + const char* code; + short priority; + short arity; + }; + + protected: + IfType* m_pType; + +}; + +/* + * + * void expression + * + */ + +class IfVoidExpression : public IfExpression { + + public: + IfVoidExpression(unsigned Flags = 0); + virtual ~IfVoidExpression() {} + + public: + virtual int IsReference() const { return 1; } + virtual int Match(const IfType*); + + public: + virtual int IsVoid() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PostCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + +}; + +/* + * + * constant expression + * + */ + +class IfConstantExpression : public IfExpression { + + public: + IfConstantExpression(IfConstant* Constant, + unsigned Flags = 0); + virtual ~IfConstantExpression(); + + public: + inline IfConstant* GetConstant() const { return m_pConstant; } + inline void SetConstant(const IfConstant* Constant) + { m_pConstant = (IfConstant*) Constant; } + + public: + virtual int IsConstant() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + protected: + IfConstant* m_pConstant; + +}; + +/* + * + * variable expression + * + */ + +class IfVariableExpression : public IfExpression { + + public: + IfVariableExpression(IfVariable* Variable, + unsigned Flags = 0); + virtual ~IfVariableExpression() {} + + public: + inline IfVariable* GetVariable() const { return m_pVariable; } + inline void SetVariable(const IfVariable* Variable) + { m_pVariable = (IfVariable*) Variable; } + + public: + virtual int IsReference() const { return 1; } + + public: + virtual int IsVariable() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfVariable* m_pVariable; + +}; + +/* + * + * call expression + * + */ + +class IfCallExpression : public IfExpression { + + public: + enum EOperator { + UNKNOWN = 0, + INSERT, REMOVE, INDEX, + OBS_QLENGTH, OBS_QGETFIRST, OBS_QGETLAST, OBS_QGETAT, + OBS_QREMOVEFIRST, OBS_QREMOVELAST, OBS_QREMOVEAT, + CALL_END_PREDEF, /* unused */ + CONSTRUCTOR, + FUNCTION + }; + + public: + IfCallExpression(char* Name, + IfList<IfExpression>* Parameters, + unsigned Flags = 0); + virtual ~IfCallExpression(); + + public: + inline int IsPredef() const + { return INSERT <= m_eOperator && m_eOperator <= CALL_END_PREDEF; } + inline int IsConstructor() const + { return CONSTRUCTOR == m_eOperator; } + inline int IsFunction() const + { return FUNCTION == m_eOperator; } + inline EOperator GetOperator() const + { return m_eOperator; } + inline IfFunction* GetFunction() const + { return m_pFunction; } + inline IfList<IfExpression>* GetParameters() const + { return m_pParameters; } + + public: + virtual int IsCall() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + protected: + virtual int Match(const IfType* Type); + virtual int MatchFunc(const IfFunction* Function); + + public: + static Operator OPERATOR[]; + + protected: + EOperator m_eOperator; + IfList<IfExpression>* m_pParameters; + IfFunction* m_pFunction; + + char* m_pName; + +}; + +/* + * + * field expression + * + */ + +class IfFieldExpression : public IfExpression { + + public: + enum EBaseKind {RECORD, PROCESS, NONE}; + + public: + IfFieldExpression(IfExpression* Base, + IfVariable* Field, + unsigned Flags = 0); + IfFieldExpression(IfExpression* Base, + char* FieldName, + unsigned Flags = 0); + virtual ~IfFieldExpression(); + + public: + inline IfExpression* GetBase() const { return m_pBase; } + inline IfVariable* GetField() const { return m_pField; } + + public: + virtual int IsReference() const + { return m_eKind == PROCESS || m_pBase->IsReference(); } + + public: + virtual int IsField() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + EBaseKind m_eKind; + IfExpression* m_pBase; + IfVariable* m_pField; + char* m_pFieldName; +}; + +/* + * + * instate expression + * + */ + +class IfInstateExpression : public IfExpression { + + public: + IfInstateExpression(IfExpression* Process, + char* StateName, + unsigned Flags = 0); + virtual ~IfInstateExpression(); + + public: + inline IfExpression* GetProcess() const { return m_pProcess; } + inline char* GetStateName() const { return m_pStateName; } + + public: + virtual int IsInstate() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + protected: + virtual void _Code(FILE* file, char* procName, IfExpression* process, IfState* rootState) const; + + protected: + IfExpression* m_pProcess; + IfState *m_pState; + char* m_pStateName; +}; + +/* + * + * instanceof expression + * + */ + +class IfInstanceofExpression : public IfExpression { + + public: + IfInstanceofExpression(IfExpression* term, + char* name, + unsigned Flags = 0); + virtual ~IfInstanceofExpression(); + + public: + inline IfExpression* GetTerm() const { return m_pTerm; } + inline char* GetName() const { return m_pName; } + + public: + virtual int IsInstanceof() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + protected: + IfExpression* m_pTerm; + IfSignal *m_pSig; + IfProcessEntity *m_pProc; + char* m_pName; +}; + +/* + * + * eventobs expression + * + */ + +class IfEventObsExpression : public IfExpression { + + public: + enum EEvtKind {INPUT, DISCARD, OUTPUT, FORK, KILL, DELIVER, INFORMAL, PROBABILITY}; + + public: + IfEventObsExpression(EEvtKind k, + char* name = NULL, + IfExpression* term1 = NULL, // INPUT:in pid, OUTPUT: ord number, FORK: in pid, KILL: killed pid, DELIVER: from pid, INFORMAL: in pid + IfExpression* term2 = NULL, // OUTPUT: from pid, KILL: in pid, + IfExpression* term3 = NULL, // OUTPUT: via pid + IfExpression* term4 = NULL, // OUTPUT: to pid + unsigned Flags = 0); + virtual ~IfEventObsExpression(); + + public: + virtual int IsEventObs() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + protected: + EEvtKind m_kind; + IfExpression* m_pTerm1; + IfExpression* m_pTerm2; + IfExpression* m_pTerm3; + IfExpression* m_pTerm4; + IfSignal *m_pSig; + IfProcessEntity *m_pProcess; + char* m_pName; +}; + +/* + * + * index expression + * + */ + +class IfIndexExpression : public IfExpression { + + public: + IfIndexExpression(IfExpression* Base, + IfExpression* Index, + unsigned Flags = 0); + virtual ~IfIndexExpression(); + + public: + inline IfExpression* GetBase() const { return m_pBase; } + inline IfExpression* GetIndex() const { return m_pIndex; } + + public: + virtual int IsReference() const + { return m_pBase->IsReference(); } + + public: + virtual int IsIndex() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pBase; + IfExpression* m_pIndex; + +}; + +/* + * + * unary expression + * + */ + +class IfUnaryExpression : public IfExpression { + + public: + enum EOperator { + ACTIVE = 0, TIMEVAL, + LENGTH, + PLUS, MINUS, + NOT + }; + + public: + IfUnaryExpression(EOperator Operator, + IfExpression* Right, + unsigned Flags = 0); + virtual ~IfUnaryExpression(); + + public: + inline EOperator GetOperator() const { return m_eOperator; } + inline IfExpression* GetRight() const { return m_pRight; } + inline void SetOperator(const EOperator Operator) { m_eOperator = Operator; } + + public: + virtual int IsUnary() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + public: + static Operator OPERATOR[]; + + protected: + EOperator m_eOperator; + IfExpression* m_pRight; + + +}; + +/* + * + * binary expression + * + */ + +class IfBinaryExpression : public IfExpression { + + public: + enum EOperator { + MULT = 0, DIV, MOD, + PLUS, MINUS, + CONCAT, + LT, LE, GE, GT, + EQ, NE, + AND, + OR, + }; + + public: + IfBinaryExpression(IfExpression* Left, + EOperator Operator, + IfExpression* Right, + unsigned Flags = 0); + virtual ~IfBinaryExpression(); + + public: + inline EOperator GetOperator() const { return m_eOperator; } + inline IfExpression* GetLeft() const { return m_pLeft; } + inline IfExpression* GetRight() const { return m_pRight; } + inline void SetOperator(const EOperator Operator) { m_eOperator = Operator; } + + public: + virtual int IsBinary() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + public: + static Operator OPERATOR[]; + + protected: + EOperator m_eOperator; + IfExpression* m_pLeft; + IfExpression* m_pRight; + +}; + +/* + * + * conditional expression + * + */ + +class IfTernaryExpression : public IfExpression { + public: + enum EOperator { + CONDITIONAL = 0, + SUBSTRING + }; + + public: + IfTernaryExpression(EOperator Operator, + IfExpression* Top, + IfExpression* Left, + IfExpression* Right, + unsigned Flags = 0); + virtual ~IfTernaryExpression(); + + public: + inline EOperator GetOperator() const { return m_eOperator; } + inline IfExpression* GetTop() const { return m_pTop; } + inline IfExpression* GetLeft() const { return m_pLeft; } + inline IfExpression* GetRight() const { return m_pRight; } + + public: + virtual int IsTernary() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + protected: + EOperator m_eOperator; + IfExpression* m_pTop; + IfExpression* m_pLeft; + IfExpression* m_pRight; + +}; + +/* + * + * cast expression + * + */ + +class IfCastExpression : public IfExpression { + + public: + enum EKind { + TYPE = 0, + PROCESS, + ROUTE + }; + + public: + IfCastExpression(EKind Kind, + IfObject* Cast, + IfExpression* Right); + IfCastExpression(EKind Kind, + char* Name, + IfExpression* Right); + virtual ~IfCastExpression(); + + public: + inline EKind GetKind() const { return m_eKind; } + inline IfExpression* GetRight() const { return m_pRight; } + inline IfObject* GetCast() const { return m_pCast; } + + public: + inline int IsType() const { return m_eKind == TYPE; } + inline int IsProcess() const { return m_eKind == PROCESS; } + inline int IsRoute() const { return m_eKind == ROUTE; } + + public: + virtual int IsCast() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + + protected: + EKind m_eKind; + IfExpression* m_pRight; + IfObject* m_pCast; + char* m_pName; + +}; + diff --git a/src/model/if.lex.l b/src/model/if.lex.l new file mode 100644 index 0000000000000000000000000000000000000000..4a670bcc68f5051e2c742f1d21c603a0c71dba48 --- /dev/null +++ b/src/model/if.lex.l @@ -0,0 +1,250 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + + +%{ // if.lex.l + +#ifdef win32native +#include <io.h> +#endif + +#define YY_NO_UNISTD_H +#define isatty(X) 0 + +#define MAXOBSEVERS 16 +YY_BUFFER_STATE hbObservers[MAXOBSEVERS]; +YY_BUFFER_STATE hbModel; +int nModelLine = 0; +int nObservers; +int nCurrentObserver = 0; + +#include "if.yacc.H" + +%} + +%option yylineno + +SPACE [ \t\n\r] +BLANC {SPACE}+ + +STAR ("*")+ +COMMENT1 "/*"([^*]|{STAR}[^*/])*{STAR}"/" +COMMENT2 "//"([^\n])* + +DIGIT [0-9] +LETTER [a-zA-Z] +ALPHA {DIGIT}|{LETTER}|_ + +INTEGER {DIGIT}+ +REAL {INTEGER}"."{INTEGER} + +IDENTIFIER {LETTER}{ALPHA}* +LITERAL {ALPHA}+ + +XSTATE {LITERAL}("@"{LITERAL})* + +OPTION #[^ \t\r\n]* + +STRING \"[^\"]*\" + +CODE "{#"([^#]|#[^}])*"#}" + + +%% + +{BLANC} { /* nothing */ } +{COMMENT1} { /* nothing */ } +{COMMENT2} { /* nothing */ } + +abstract { return ABSTRACT_K; } +active { return ACTIVE_K; } +acquire { return ACQUIRE_K; } +and { return (STATUS & WHEN) ? ',' : AND_K; } +array { return ARRAY_K; } +call { return CALL_K; } +fork { return FORK_K; } +const { return CONST_K; } +deadline { return DEADLINE_K; } +discard { return DISCARD_K; } +do { return DO_K; } +else { return ELSE_K; } +endabstract { return ENDABSTRACT_K; } +endenum { return ENDENUM_K; } +endif { return ENDIF_K; } +endprocedure { return ENDPROCEDURE_K; } +endprocess { return ENDPROCESS_K; } +endrecord { return ENDRECORD_K; } +endstate { return ENDSTATE_K; } +endsystem { return ENDSYSTEM_K; } +endwhile { return ENDWHILE_K; } +enum { return ENUM_K; } +env { return ENV_K; } +false { return FALSE_K; } +fpar { return FPAR_K; } +from { return FROM_K; } +if { return IF_K; } +in { return IN_K; } +informal { return INFORMAL_K; } +input { return INPUT_K; } +inout { return INOUT_K; } +instanceof { return INSTANCEOF_K; } +instate { return INSTATE_K; } +kill { return KILL_K; } +length { return LENGTH_K; } +nextstate { return NEXTSTATE_K; } +nil { return NIL_K; } +not { return NOT_K; } +of { return OF_K; } +or { return OR_K; } +out { return OUT_K; } +output { return OUTPUT_K; } +priority { return PRIORITY_K; } +private { return PRIVATE_K; } +probability { return PROBABILITY_K; } +procedure { return PROCEDURE_K; } +process { return PROCESS_K; } +provided { return PROVIDED_K; } +public { return PUBLIC_K; } +range { return RANGE_K; } +record { return RECORD_K; } +release { return RELEASE_K; } +reset { return RESET_K; } +resource { return RESOURCE_K; } +returns { return RETURNS_K; } +save { return SAVE_K; } +self { return SELF_K; } +set { return SET_K; } +signal { return SIGNAL_K; } +signalroute { return SIGNALROUTE_K; } +skip { return SKIP_K; } +state { return STATE_K; } +stop { return STOP_K; } +string { return STRING_K; } +system { return SYSTEM_K; } +task { return TASK_K; } +timeval { return TIMEVAL_K; } +then { return THEN_K; } +to { return TO_K; } +tpc { return TPC_K; } +tree { return TREE_K; } +true { return TRUE_K; } +type { return TYPE_K; } +var { return VAR_K; } +via { return VIA_K; } +void { return VOID_K; } +with { return WITH_K; } +when { return WHEN_K; } +while { return WHILE_K; } + + + +endobserver { return ENDOBSERVER_K; } +flush { return FLUSH_K; } +cut { return CUT_K; } +observer { return OBSERVER_K; } +obsoutput { return OBSOUTPUT_K; } +obsinput { return OBSINPUT_K; } +obsfork { return OBSFORK_K; } +obskillpid { return OBSKILLPID_K; } +obskillprocess { return OBSKILLPROCESS_K; } +match { return MATCH_K; } +deliver { return DELIVER_K; } +pure { return PURE_K; } +intrusive { return INTRUSIVE_K; } + + +priorityrules { return PRIORITY_SECTION_K;} +endpriorityrules { return END_PRIORITY_SECTION_K;} +{REAL} { return _REAL_; } + +{INTEGER} { return _INTEGER_; } +{IDENTIFIER} { return _IDENTIFIER_; } +{LITERAL} { return _LITERAL_; } +{XSTATE} { return _XSTATE_; } +{OPTION} { return _OPTION_; } +{STRING} { return _STRING_; } +{CODE} { return _CODE_; } + +".." { return DDOT_K; } +":=" { return DOTSEQ_K; } +"<=" { return LE_K; } +">=" { return GE_K; } +"<>" { return NE_K; } + +"(" { return '('; } +")" { return ')'; } +"[" { return '['; } +"]" { return ']'; } +"{" { return '{'; } +"}" { return '}'; } +"+" { return '+'; } +"-" { return '-'; } +"*" { return '*'; } +"/" { return '/'; } +"%" { return '%'; } +"^" { return '^'; } +"<" { return '<'; } +">" { return '>'; } +"=" { return '='; } +"." { return '.'; } +";" { return ';'; } +":" { return ':'; } +"," { return ','; } +"?" { return '?'; } + +. { fprintf(stderr, "line %d : lexical error (at or near `%s')\n", + yylineno, yytext); + exit(1); } + +<<EOF>> { + if(nCurrentObserver < nObservers) { + yy_switch_to_buffer(hbObservers[nCurrentObserver]); + nCurrentObserver++; + yylineno = 1; + } else { + yyterminate(); + } + } + +%% + +extern "C" int yywrap(){ /* yywrap implementation */ + return 1; +} diff --git a/src/model/if.yacc.y b/src/model/if.yacc.y new file mode 100644 index 0000000000000000000000000000000000000000..b356d826a14995947fdea2a55ef86707bf65a889 --- /dev/null +++ b/src/model/if.yacc.y @@ -0,0 +1,1361 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + + +%{ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "model.h" + +extern int yylex(); /* scanner function */ +extern char* yytext; /* scanner token */ +extern int yylineno; /* current line number */ +extern FILE* yyin; + +IfSystemEntity* SYSTEM; /* system entity */ +IfAutomatonEntity* PROCESS; /* process or observer entity */ +IfPriorityRuleEntity* PRIORITYRULE; /* priority rule entity */ + +IfState* STACK[32]; /* state stack (max 32 nesting) */ +IfState* *STATE = STACK; + +static int STATUS = 0; /* internal (compilation) */ + +enum { + WHEN = 1, /* solve AND_K conflicts (constraint) */ + ABSTRACT = 2 /* solve abstract type cross definitions */ +}; + +#ifdef CYGWIN +int isatty(int desc) +{ + return 1; +} +#endif + +/* + * + * contextual name binding + * + */ + +IfObject* Bind(const IfEntity* Entity, + const char* Name, + const char Kind) { + IfObject* object = NULL; + int i; + switch (Kind) { + case 'C': // constants + object = Entity->GetConstants()->Find(Name); + for(i = 0; i < Entity->GetTypes()->GetCount() && !object; i++) + if (Entity->GetTypes()->GetAt(i)->IsEnum()) { + IfEnumType* type = (IfEnumType*) Entity->GetTypes()->GetAt(i); + object = type->GetLiterals()->Find(Name); + } + break; + case 'F': // functions + for(i = 0; i < Entity->GetTypes()->GetCount() && !object; i++) + if (Entity->GetTypes()->GetAt(i)->IsAbstract()) { + IfAbstractType* type = (IfAbstractType*) Entity->GetTypes()->GetAt(i); + object = type->GetFunctions()->Find(Name); + } + break; + case 'V': // variables + object = Entity->GetVariables()->Find(Name); + if (Entity->IsProcess() && !object) + object = ((IfProcessEntity*) Entity)->GetParameters()->Find(Name); + break; + case 'T': // types + object = Entity->TYPES.Find(Name); + if (!object) + object = Entity->GetTypes()->Find(Name); + break; + case 'M': // procedures + object = Entity->GetProcedures()->Find(Name); + break; + case 'S': // signal + if (Entity->IsSystem()) + object = ((IfSystemEntity*) Entity)->GetSignals()->Find(Name); + break; + case 'R': // signalroutes + if (Entity->IsSystem()) + object = ((IfSystemEntity*) Entity)->GetSignalroutes()->Find(Name); + break; + case 'X': // resources + if (Entity->IsSystem()) + object = ((IfSystemEntity*) Entity)->GetResources()->Find(Name); + break; + default: // unknown + break; + } + return object; +} + +IfObject* Bind(const char* Name, const char Kind) { + IfObject* object = NULL; + + if (!object && Kind=='V' && PRIORITYRULE) { + if(!strcmp(PRIORITYRULE->GetProcessVar1()->GetName(), Name)) + object = PRIORITYRULE->GetProcessVar1(); + if(!strcmp(PRIORITYRULE->GetProcessVar2()->GetName(), Name)) + object = PRIORITYRULE->GetProcessVar2(); + } + if (!object && PROCESS) object = Bind(PROCESS, Name, Kind); + if (!object && SYSTEM) object = Bind(SYSTEM, Name, Kind); + + return object; +} + +/* + * + * error handling + * + */ + +void yyerror(const char* msg) { + fprintf(stderr, "line %d : %s (at or near `%s')\n", + yylineno, msg, yytext); + exit(1); +} + +void yywarning(const char* msg) { + fprintf(stderr, "line %d : %s (at or near `%s')\n", + yylineno, msg, yytext); +} + +#include "if.lex.i" + +%} + +%expect 0 + +%union{ + IfConstant* constant; + IfList<IfConstant>* constant_list; + IfEnumConstant* literal; + IfList<IfEnumConstant>* literal_list; + IfFunction* function; + IfList<IfFunction>* function_list; + IfType* type; + IfList<IfType>* type_list; + IfVariable::EKind vkind; + IfVariable::EScope scope; + IfVariable::EMode mode; + IfVariable* variable; + IfList<IfVariable>* variable_list; + IfExpression* expression; + IfList<IfExpression>* expression_list; + IfConstraint* constraint; + IfResource* resource; + IfList<IfResource>* resource_list; + IfSignal* signal; + IfList<IfSignal>* signal_list; + IfSignalroute* signalroute; + IfProcedure* procedure; + IfAction* action; + IfBasicStatement* statement; + IfBlockStatement* block; + IfTransition* transition; + IfList<IfTransition>* transition_list; + IfList<IfObject>* transition_state_decl_list; + IfTransition::EDeadline deadline; + IfState* state; + IfList<IfState>* state_list; + IfEntity* entity; + IfList<IfEntity>* entity_list; + IfPriorityRuleEntity* priority_rule; + IfList<IfPriorityRuleEntity>* priority_rule_list; + char* name; + char** name_list; + int integer; + float probability; +} + +%type <constant> constant constant_decl constant_body constant_value + +%type <literal> enum_decl +%type <literal_list> enum_decl_list + +%type <function> function_decl +%type <function_list> function_decl_set + +%type <type> type type_decl type_body type_value returns_opt +%type <type_list> type_list type_opt_list + +%type <variable> field_decl variable_decl fpar_decl +%type <variable_list> field_decl_set fpar_decl_opt_list fpar_decl_list + +%type <scope> scope + +%type <expression> expression expression_opt provided_opt to_opt via_opt initializer obs_opt_in obs_output_opt_ord obs_output_opt_from priority_expression + +%type <expression_list> expression_list expression_opt_list + +%type <constraint> constraint when_opt tpc_opt + +%type <resource> resource resource_decl +%type <resource_list> resource_list + +%type <signal> signal signal_decl +%type <signal_list> signal_list save_opt + +%type <signalroute> signalroute_decl + +%type <mode> fpar_mode +%type <procedure> procedure procedure_decl + +%type <action> action input input_opt terminator + +%type <action> match match_input match_discard match_output match_fork match_kill match_deliver match_informal match_probability + +%type <action> acquire acquire_opt + +%type <block> block +%type <statement> statement + +%type <transition> transition + +%type <deadline> deadline_opt + +%type <state> state_decl + +%type <transition_state_decl_list> transition_state_decl_set + +%type <entity> process_decl system_decl observer_decl + +%type <name> constant_name type_name function_name +%type <name> field_name variable_name fpar_name name +%type <name> signal_name signalroute_name signalroute_endpoint +%type <name> state_name state_reference procedure_name process_name system_name process_name_opt +%type <name> resource_name +%type <name> string code_opt option + +%type <name_list> option_set + +%type <integer> integer priority_opt obs_kind + +%type <probability> probability_opt + +%type <name> priority_rule_id +%type <priority_rule> priority_decl +%type <priority_rule_list> priority_decl_set +%type <priority_rule_list> priority_section + +%token _IDENTIFIER_ _LITERAL_ _XSTATE_ _STRING_ _CODE_ _OPTION_ + +%token CONST_K TRUE_K FALSE_K SELF_K NIL_K _INTEGER_ _REAL_ + +%token TYPE_K ENUM_K ENDENUM_K RANGE_K DDOT_K ARRAY_K TREE_K OF_K +%token RECORD_K ENDRECORD_K STRING_K ABSTRACT_K ENDABSTRACT_K + +%token VAR_K PUBLIC_K PRIVATE_K + +%token VOID_K NOT_K UMIN_K ACTIVE_K TIMEVAL_K LENGTH_K +%token LE_K GE_K NE_K AND_K OR_K +%token INSTATE_K +%token INSTANCEOF_K + +%token SIGNAL_K SIGNALROUTE_K FROM_K TO_K WITH_K ENV_K + +%token RESOURCE_K + +%token PROCEDURE_K ENDPROCEDURE_K +%token FPAR_K IN_K INOUT_K OUT_K RETURNS_K + +%token SKIP_K INFORMAL_K TASK_K SET_K RESET_K STOP_K FLUSH_K CUT_K +%token INPUT_K OUTPUT_K VIA_K DOTSEQ_K +%token OBSINPUT_K OBSOUTPUT_K OBSFORK_K OBSKILLPID_K OBSKILLPROCESS_K +%token MATCH_K DELIVER_K DISCARD_K +%token FORK_K KILL_K CALL_K NEXTSTATE_K +%token ACQUIRE_K RELEASE_K + +%token IF_K THEN_K ELSE_K ENDIF_K +%token WHILE_K DO_K ENDWHILE_K + +%token DEADLINE_K PRIORITY_K PROVIDED_K WHEN_K PROBABILITY_K + +%token STATE_K ENDSTATE_K SAVE_K TPC_K + + +%token PROCESS_K ENDPROCESS_K +%token OBSERVER_K ENDOBSERVER_K +%token INTRUSIVE_K PURE_K + +%token SYSTEM_K ENDSYSTEM_K +%token PRIORITY_SECTION_K END_PRIORITY_SECTION_K +%nonassoc OBSOUTPUT_K '?' ':' + +%left ',' + +%left OR_K + +%left AND_K + +%left '=' NE_K + +%left '>' '<' LE_K GE_K + +%nonassoc '{' '}' + +%left '^' + +%left '+' '-' + +%left '*' '/' '%' + +%right NOT_K + +%right UMIN_K + +%right ACTIVE_K TIMEVAL_K LENGTH_K + +%left '.' + +%nonassoc '[' ']' '(' ')' + +%nonassoc INSTATE_K INSTANCEOF_K OBSKILLPID_K IN_K FROM_K VIA_K TO_K + +%start system_decl + +%% + +/* +-------------------------------------------------------------------- +Constant +-------------------------------------------------------------------- +*/ + +constant_decl : + CONST_K constant_name '=' constant_body ';' + { $$ = $4; $4->SetName($2); } +; + +constant_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +| _LITERAL_ { $$ = strdup(yytext); } +; + +constant_body : + constant_value { $$ = $1; } +| constant { $$ = new IfOtherConstant($1, NULL); } +; + +constant_value : + TRUE_K { $$ = new IfBooleanConstant(IfBooleanConstant::TRUE, NULL); } +| FALSE_K { $$ = new IfBooleanConstant(IfBooleanConstant::FALSE, NULL); } +| _INTEGER_ { $$ = new IfIntegerConstant(atoi(yytext), NULL); } +| _REAL_ { $$ = new IfRealConstant(atof(yytext), NULL); } +| SELF_K { $$ = new IfPidConstant(IfPidConstant::SELF, NULL); } +| NIL_K { $$ = new IfPidConstant(IfPidConstant::NIL, NULL); } +; + +constant: + constant_name + { $$ = (IfConstant*) Bind($1, 'C'); free($1); + if (!$$) yyerror("undefined constant"); } +; + +/* +-------------------------------------------------------------------- +Type +-------------------------------------------------------------------- +*/ + +type_decl : + TYPE_K type_name '=' type_body ';' + { $$ = $4; $$->SetName($2); } +; + +type_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +type_body : + type_value { $$ = $1; } +| type { $$ = new IfOtherType($1, NULL); } +; + +type_value : + ENUM_K enum_decl_list ENDENUM_K + { $$ = new IfEnumType($2, NULL); } +| RANGE_K constant_body DDOT_K constant_body + { $$ = new IfRangeType($2, $4, NULL); } +| RECORD_K field_decl_set ENDRECORD_K + { $$ = new IfRecordType($2, NULL); } +| ARRAY_K '[' constant_body ']' OF_K type + { $$ = new IfArrayType($3, $6, NULL); } +| STRING_K '[' constant_body ']' OF_K type + { $$ = new IfStringType($3, $6, NULL); } +| TREE_K '[' constant_body ',' constant_body ']' OF_K type + { $$ = new IfTreeType($3, $5, $8, NULL); } +| ABSTRACT_K { STATUS |= ABSTRACT; } function_decl_set ENDABSTRACT_K + { IfAbstractType* at = new IfAbstractType($3, NULL); at->Link(); + $$ = at; STATUS &= ~ABSTRACT; } +; + +type : + type_name + { $$ = (IfType*) Bind($1, 'T'); free($1); + if (!$$ && (STATUS & ABSTRACT)) + $$ = (IfType*) 1; + if (!$$) yyerror("undefined type"); } +; + + +type_opt_list : + type_list { $$ = $1; } +| /* empty */ { $$ = new IfList<IfType>; } +; + +type_list : + type_list ',' type { $$ = $1; $$->Add($3); } +| type { $$ = new IfList<IfType>; $$->Add($1); } +; + +/* +-------------------------------------------------------------------- +*/ + +enum_decl : + constant_name { $$ = new IfEnumConstant($1); } +; + +enum_decl_list : + enum_decl_list ',' enum_decl { $$ = $1; $$->Add($3); } +| enum_decl { $$ = new IfList<IfEnumConstant>(1); $$->Add($1); } +; + +/* +-------------------------------------------------------------------- +*/ + +field_decl : + field_name type ';' + { $$ = new IfVariable(IfVariable::FIELD, IfVariable::NOSCOPE, IfVariable::NOMODE, + $2, NULL, $1); } +; + +field_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +field_decl_set : + field_decl_set field_decl { $$ = $1; $$->Add($2); } +| { $$ = new IfList<IfVariable>(1); } +; + +/* +-------------------------------------------------------------------- +*/ + +function_decl : + type function_name '(' type_opt_list ')' ';' + { $$ = new IfFunction($4, $1, $2); } +; + +function_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +function_decl_set : + function_decl_set function_decl { $$ = $1; $$->Add($2); } +| /* empty */ { $$ = new IfList<IfFunction>(1); } +; + + +/* +-------------------------------------------------------------------- +Variable Definition +-------------------------------------------------------------------- +*/ + +variable_decl : + VAR_K variable_name type initializer scope ';' + { $$ = new IfVariable(IfVariable::VAR, $5, IfVariable::NOMODE, + $3, $4, $2); } +; + +variable_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +scope : + PUBLIC_K { $$ = IfVariable::PUBLIC; } +| PRIVATE_K { $$ = IfVariable::PRIVATE; } +| /* empty */ { $$ = IfVariable::NOSCOPE; } +; + +initializer : + DOTSEQ_K expression { $$ = $2; } +| /* empty */ { $$ = NULL; } +; + +/* +-------------------------------------------------------------------- +Expression +-------------------------------------------------------------------- +*/ + +expression : + VOID_K + { $$ = new IfVoidExpression(); } +| constant_value + { $$ = new IfConstantExpression($1); } +| name '(' expression_opt_list ')' + { $$ = new IfCallExpression($1, $3); } +| name + { IfConstant* constant = (IfConstant*) Bind($1, 'C'); + IfVariable* variable = (IfVariable*) Bind($1, 'V'); free($1); + $$ = NULL; + if (!$$ && constant) $$ = new IfConstantExpression(constant); + if (!$$ && variable) $$ = new IfVariableExpression(variable); + if (!$$) yyerror("undefined reference"); } +| expression '.' name + { $$ = new IfFieldExpression($1, $3); } +| expression '[' expression ']' + { $$ = new IfIndexExpression($1, $3); } +| expression '[' expression ':' expression ']' + { $$ = new IfTernaryExpression(IfTernaryExpression::SUBSTRING, $1, $3, $5); } +| '{' name '}' expression + { IfObject* object = NULL; + $$ = NULL; + if ($$ == NULL && (object = Bind($2, 'T')) != NULL) + $$ = new IfCastExpression(IfCastExpression::TYPE, object, $4); + if ($$ == NULL && (object = Bind($2, 'R')) != NULL) + $$ = new IfCastExpression(IfCastExpression::ROUTE, object, $4); + if ($$ == NULL) + $$ = new IfCastExpression(IfCastExpression::PROCESS, $2, $4); + else + free($2); } +| ACTIVE_K expression + { $$ = new IfUnaryExpression(IfUnaryExpression::ACTIVE, $2); } +| TIMEVAL_K expression + { $$ = new IfUnaryExpression(IfUnaryExpression::TIMEVAL, $2); } +| LENGTH_K expression + { $$ = new IfUnaryExpression(IfUnaryExpression::LENGTH, $2); } +| '+' expression %prec UMIN_K + { $$ = new IfUnaryExpression(IfUnaryExpression::PLUS, $2); } +| '-' expression %prec UMIN_K + { $$ = new IfUnaryExpression(IfUnaryExpression::MINUS, $2); } +| NOT_K expression + { $$ = new IfUnaryExpression(IfUnaryExpression::NOT, $2); } +| expression '*' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::MULT, $3); } +| expression '/' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::DIV, $3); } +| expression '%' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::MOD, $3); } +| expression '+' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::PLUS, $3); } +| expression '-' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::MINUS, $3); } +| expression '^' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::CONCAT, $3); } +| expression '<' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::LT, $3); } +| expression '>' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::GT, $3); } +| expression LE_K expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::LE, $3); } +| expression GE_K expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::GE, $3); } +| expression '=' expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::EQ, $3); } +| expression NE_K expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::NE, $3); } +| expression AND_K expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::AND, $3); } +| expression OR_K expression + { $$ = new IfBinaryExpression($1, IfBinaryExpression::OR, $3); } +| expression '?' expression ':' expression + { $$ = new IfTernaryExpression(IfTernaryExpression::CONDITIONAL, $1, $3, $5); } +| '(' expression ')' + { $$ = $2; } +/* special observer expressions */ +| expression INSTATE_K name + { $$ = new IfInstateExpression($1, $3); } +| expression INSTANCEOF_K name + { $$ = new IfInstanceofExpression($1, $3); } +| expression INSTANCEOF_K '*' + { $$ = new IfInstanceofExpression($1, NULL); } +| OBSINPUT_K '(' name obs_opt_in ')' + { $$ = new IfEventObsExpression(IfEventObsExpression::INPUT, $3, $4); } +| OBSOUTPUT_K '(' name obs_output_opt_ord obs_output_opt_from via_opt to_opt ')' + { $$ = new IfEventObsExpression(IfEventObsExpression::OUTPUT, $3, $4, $5, $6, $7); } +| OBSFORK_K '(' process_name_opt obs_opt_in ')' + { $$ = new IfEventObsExpression(IfEventObsExpression::FORK, $3, $4); } +| OBSKILLPID_K '(' expression ')' + { $$ = new IfEventObsExpression(IfEventObsExpression::KILL, NULL, $3); } +| OBSKILLPROCESS_K '(' name ')' + { $$ = new IfEventObsExpression(IfEventObsExpression::KILL, $3, NULL); } +; + +obs_opt_in : + IN_K expression + { $$ = $2; } +| /* empty */ + { $$ = NULL; } +; + +obs_output_opt_ord : + '[' expression ']' + { $$ = $2; } +| /* empty */ + { $$ = NULL; } +; + +obs_output_opt_from : + FROM_K expression + { $$ = $2; } +| /* empty */ + { $$ = NULL; } +; + +name : + _IDENTIFIER_ { $$ = strdup(yytext); } +| _LITERAL_ { $$ = strdup(yytext); } +; + + +expression_opt_list : + expression_list { $$ = $1; } +| /* empty */ { $$ = new IfList<IfExpression>(1); } +; + +expression_list : + expression_list ',' expression { $$ = $1; $$->Add($3); } +| expression { $$ = new IfList<IfExpression>(1); $$->Add($1); } +; + + +priority_expression : + expression { $$ = $1;} +; +/* +-------------------------------------------------------------------- +Constraint +-------------------------------------------------------------------- +*/ + +constraint : + expression '<' expression + { $$ = new IfBasicConstraint($1, NULL, IfBasicConstraint::LT, $3); } +| expression LE_K expression + { $$ = new IfBasicConstraint($1, NULL, IfBasicConstraint::LE, $3); } +| expression '=' expression + { $$ = new IfBasicConstraint($1, NULL, IfBasicConstraint::EQ, $3); } +| expression GE_K expression + { $$ = new IfBasicConstraint($1, NULL, IfBasicConstraint::GE, $3); } +| expression '>' expression + { $$ = new IfBasicConstraint($1, NULL, IfBasicConstraint::GT, $3); } +| constraint ',' constraint + { IfComposedConstraint* C = NULL; + if ($1->IsBasic()) { + C = new IfComposedConstraint(new IfList<IfBasicConstraint>(1)); + C->GetConstraints()->Add((IfBasicConstraint*) $1); + } + else + C = (IfComposedConstraint*)$1; + C->GetConstraints()->Add((IfBasicConstraint*) $3); + $$ = C; + } +; + +/* +-------------------------------------------------------------------- +Resource +-------------------------------------------------------------------- +*/ + +resource_decl : + RESOURCE_K resource_name ';' + { $$ = new IfResource($2); } +; + +resource_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +resource : + resource_name + { $$ = (IfResource*) Bind($1, 'X'); free($1); + if (!$$) yyerror("undefined resource"); } +; + +resource_list : + resource_list ',' resource { $$ = $1; $$->Add($3); } +| resource { $$ = new IfList<IfResource>; $$->Add($1); } +; + +/* +-------------------------------------------------------------------- +Signal +-------------------------------------------------------------------- +*/ + +signal_decl : + SIGNAL_K signal_name '(' type_opt_list ')' ';' + { + $$ = new IfSignal($4, $2); + } +; + +signal_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +signal : + signal_name + { $$ = (IfSignal*) Bind($1, 'S'); free($1); + if (!$$) yyerror("undefined signal"); } +; + +signal_list : + signal_list ',' signal { $$ = $1; $$->Add($3); } +| signal { $$ = new IfList<IfSignal>; $$->Add($1); } +; + +/* +-------------------------------------------------------------------- +Signalroute +-------------------------------------------------------------------- +*/ + +signalroute_decl : + SIGNALROUTE_K signalroute_name '(' constant_body ')' option_set + FROM_K signalroute_endpoint TO_K signalroute_endpoint + WITH_K signal_list ';' + { $$ = new IfSignalroute($4, $6, $8, $10, $12, $2); + for(int i = 0; $6[i]; i++) free($6[i]); free($6); } +; + +signalroute_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +signalroute_endpoint : + ENV_K { $$ = strdup("env"); } +| process_name { $$ = $1; } +; + +/* +-------------------------------------------------------------------- +Procedure +-------------------------------------------------------------------- +*/ + +procedure_decl : + PROCEDURE_K procedure_name ';' + fpar_decl_opt_list + returns_opt + code_opt + ENDPROCEDURE_K ';' + { $$ = new IfProcedure($4, $5, $6, $2); } +; + +procedure_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +procedure : + procedure_name + { $$ = (IfProcedure*) Bind($1, 'M'); free($1); + if (!$$) yyerror("undefined procedure"); } +; + +returns_opt : + RETURNS_K type ';' { $$ = $2; } +| /* empty */ { $$ = NULL; } +; + +code_opt : + _CODE_ { $$ = strdup(yytext); } +| /* empty */ { $$ = NULL; } +; + +/* +-------------------------------------------------------------------- +Input / Action +-------------------------------------------------------------------- +*/ + +input: + INPUT_K signal '(' expression_opt_list ')' ';' + { $$ = new IfInputAction($2, $4); } +; + +match: + match_input { $$ = $1; } +| match_discard { $$ = $1; } +| match_output { $$ = $1; } +| match_fork { $$ = $1; } +| match_kill { $$ = $1; } +| match_deliver { $$ = $1; } +| match_informal { $$ = $1; } +| match_probability { $$ = $1; } +; + +match_input : + MATCH_K INPUT_K signal '(' expression_opt_list ')' obs_opt_in ';' + { $$ = new IfMatchInputAction($3, $5, NULL, $7); } +| MATCH_K INPUT_K '(' expression_opt ')' obs_opt_in ';' + { $$ = new IfMatchInputAction(NULL, NULL, $4, $6); } +; + +match_discard : + MATCH_K DISCARD_K signal '(' expression_opt_list ')' obs_opt_in ';' + { $$ = new IfMatchInputAction($3, $5, NULL, $7, 1); } +| MATCH_K DISCARD_K '(' expression_opt ')' obs_opt_in ';' + { $$ = new IfMatchInputAction(NULL, NULL, $4, $6, 1); } +; + +match_output : + MATCH_K OUTPUT_K signal '(' expression_opt_list ')' obs_output_opt_ord obs_output_opt_from via_opt to_opt ';' + { $$ = new IfMatchOutputAction($3, $5, NULL, $7, $8, $9, $10); } +| MATCH_K OUTPUT_K '(' expression_opt ')' obs_output_opt_ord obs_output_opt_from via_opt to_opt ';' + { $$ = new IfMatchOutputAction(NULL, NULL, $4, $6, $7, $8, $9); } +; + +match_fork : + MATCH_K FORK_K '(' expression_opt ')' process_name_opt obs_opt_in ';' + { $$ = new IfMatchForkAction($6, $4, $7); } +; + +match_kill : + MATCH_K KILL_K '(' expression_opt ')' process_name_opt obs_opt_in ';' + { $$ = new IfMatchKillAction($6, $4, $7); } +; + +match_deliver : + MATCH_K DELIVER_K signal '(' expression_opt_list ')' obs_output_opt_from ';' + { $$ = new IfMatchDeliverAction($3, $5, NULL, $7); } +| MATCH_K DELIVER_K '(' expression_opt ')' obs_output_opt_from ';' + { $$ = new IfMatchDeliverAction(NULL, NULL, $4, $6); } +; + +match_informal : + MATCH_K INFORMAL_K string obs_opt_in ';' + { $$ = new IfMatchInformalAction($3, $4); } +; + +match_probability : + MATCH_K PROBABILITY_K '(' expression_opt ')' ';' + { $$ = new IfMatchProbabilityAction($4); } +; + +process_name_opt : + process_name + { $$ = $1; } +| /* empty */ + { $$ = NULL; } +; + +expression_opt : + expression + { $$ = $1; } +| /* empty */ + { $$ = NULL; } +; + +acquire: + ACQUIRE_K resource_list ';' + { $$ = new IfAcquireAction($2); } +; + +/* +-------------------------------------------------------------------- +*/ + +action : + SKIP_K ';' + { $$ = new IfSkipAction(); } +| INFORMAL_K string ';' + { $$ = new IfInformalAction($2); } +| TASK_K expression DOTSEQ_K expression ';' + { $$ = new IfTaskAction($2, $4); } +| SET_K expression DOTSEQ_K expression ';' + { $$ = new IfSetAction($2, $4); } +| RESET_K expression ';' + { $$ = new IfResetAction($2); } +| OUTPUT_K signal '(' expression_opt_list ')' via_opt to_opt ';' + { $$ = new IfOutputAction($2, $4, $6, $7); } +| RELEASE_K resource_list ';' + { $$ = new IfReleaseAction($2); } +| FORK_K process_name '(' expression_opt_list ')' ';' + { $$ = new IfForkAction(NULL, $2, $4); } +| expression DOTSEQ_K FORK_K process_name '(' expression_opt_list ')' ';' + { $$ = new IfForkAction($1, $4, $6); } +| KILL_K expression ';' + { $$ = new IfKillAction($2); } +| CALL_K procedure '(' expression_opt_list ')' ';' + { $$ = new IfCallAction(NULL, $2, $4); } +| expression DOTSEQ_K CALL_K procedure '(' expression_opt_list ')' ';' + { $$ = new IfCallAction($1, $4, $6); } +| FLUSH_K ';' + { $$ = new IfFlushAction(); } +| CUT_K ';' + { $$ = new IfCutAction(); } +; + +string : + _STRING_ { $$ = strdup(yytext); } +; + +via_opt : + VIA_K expression { $$ = $2; } +| /* empty */ { $$ = NULL; } +; + +to_opt : + TO_K expression { $$ = $2; } +| /* empty */ { $$ = NULL; } +; + +/* +-------------------------------------------------------------------- +*/ + +terminator : + NEXTSTATE_K state_reference ';' + { $$ = new IfNextstateAction($2); } +| STOP_K ';' + { $$ = new IfStopAction(); } +; + +state_reference : + state_name { $$ = $1; } +| _XSTATE_ { $$ = strdup(yytext); } +| '-' { $$ = strdup("-"); } +; + +/* +-------------------------------------------------------------------- +Statement +-------------------------------------------------------------------- +*/ + +block : + block statement + { $$ = $1; $$->GetStatements()->Add($2); } +| /* empty */ + { $$ = new IfBlockStatement(new IfList<IfBasicStatement>(1)); } +; + +statement : + action + { $$ = new IfActionStatement($1); } +| IF_K expression THEN_K block ENDIF_K + { $$ = new IfConditionalStatement($2, $4, NULL); } +| IF_K expression THEN_K block ELSE_K block ENDIF_K + { $$ = new IfConditionalStatement($2, $4, $6); } +| WHILE_K expression DO_K block ENDWHILE_K + { $$ = new IfLoopStatement($2, $4); } +; + +/* +-------------------------------------------------------------------- +Transition +-------------------------------------------------------------------- +*/ + +transition : + probability_opt + deadline_opt + priority_opt + acquire_opt + provided_opt + when_opt + input_opt + block + terminator + { $$ = new IfTransition($1, $2, $3, $4, $5, $6, $7, $8, $9); } +; + +probability_opt : + PROBABILITY_K constant_value ';' + { + if( !$2->IsReal() ) + yyerror("real constant expected in probability clause"); + if( ((IfRealConstant*)$2)->GetValue() < 0 || ((IfRealConstant*)$2)->GetValue() > 1 ) + yyerror("real constant within [0,1] expected in probability clause"); + + $$ = ((IfRealConstant*)$2)->GetValue(); + } +| /* empty */ + { + $$ = -1; + } +; + +deadline_opt : + DEADLINE_K name ';' + { + if( PROCESS->IsObserver() ) + $$ = IfTransition::LAZY; + else + $$ = IfTransition::EAGER; + if (!strcmp($2, "delayable")) $$ = IfTransition::DELAYABLE; + if (!strcmp($2, "lazy")) $$ = IfTransition::LAZY; + free($2);} +| /* empty */ + { + if( PROCESS->IsObserver() ) + $$ = IfTransition::LAZY; + else + $$ = IfTransition::EAGER; + } +; + +priority_opt : + PRIORITY_K integer ';' { $$ = $2; } +| /* empty */ { $$ = -1; } +; + +acquire_opt : + acquire { $$ = $1; } +| /* empty */ { $$ = NULL; } +; + +provided_opt : + PROVIDED_K expression ';' { $$ = $2; } +| /* empty */ { $$ = NULL; } +; + +when_opt : + WHEN_K { STATUS |= WHEN; } constraint ';' { $$ = $3; STATUS &= ~WHEN; } +| /* empty */ { $$ = NULL; } +; + +input_opt : + input + { + if(PROCESS->IsObserver()) yyerror("input clause not allowed in observer"); + $$ = $1; + } +| match + { + if(!PROCESS->IsObserver()) yyerror("match clause only allowed in observer"); + $$ = $1; + } +| /* empty */ { $$ = NULL; } +; + +/* +-------------------------------------------------------------------- +State +-------------------------------------------------------------------- +*/ + +state_decl : + STATE_K state_name option_set ';' + tpc_opt + save_opt + transition_state_decl_set + ENDSTATE_K ';' + { IfList<IfTransition>* transitions = new IfList<IfTransition>(1); + IfList<IfState>* state_decls = new IfList<IfState>(1); + for(int ii = 0; ii < $7->GetCount(); ii++) + if(!strcmp($7->GetAt(ii)->GetClass(), "transition")) + transitions->Add( (IfTransition*)($7->GetAt(ii)) ); + else + state_decls->Add( (IfState*)($7->GetAt(ii)) ); + delete $7; + + $$ = new IfState($5, $6, transitions, state_decls, $3, $2); + for(int i = 0; $3[i]; i++) free($3[i]); free($3); } +; + +state_name : + _INTEGER_ { $$ = strdup(yytext); } +| _IDENTIFIER_ { $$ = strdup(yytext); } +| _LITERAL_ { $$ = strdup(yytext); } +; + +tpc_opt : + TPC_K constraint ';' { $$ = $2; } +| /* empty */ { $$ = NULL; } +; + +save_opt : + SAVE_K signal_list ';' { $$ = $2; } +| /* empty */ { $$ = new IfList<IfSignal>; } +; + +transition_state_decl_set : + transition_state_decl_set state_decl { $$ = $1; $$->Add($2); } +| transition_state_decl_set transition { $$ = $1; $$->Add($2); } +| /* empty */ { $$ = new IfList<IfObject>(0); } +; + +/* +-------------------------------------------------------------------- +Process +-------------------------------------------------------------------- +*/ + +fpar_decl : + fpar_mode fpar_name type + { $$ = new IfVariable(IfVariable::FPAR, IfVariable::NOSCOPE, $1, + $3, NULL, $2); } +; + +fpar_mode : + IN_K { $$ = IfVariable::IN; } +| INOUT_K { $$ = IfVariable::INOUT; } +| OUT_K { $$ = IfVariable::OUT; } +| /* empty */ { $$ = IfVariable::NOMODE; } +; + +fpar_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +fpar_decl_opt_list : + fpar_decl_list ';' { $$ = $1; } +| /* empty */ { $$ = new IfList<IfVariable>(1); } +; + +fpar_decl_list : + fpar_decl_list ',' fpar_decl { $$ = $1; $$->Add($3); } +| FPAR_K fpar_decl { $$ = new IfList<IfVariable>(1); $$->Add($2); } +; + +/* +-------------------------------------------------------------------- +*/ + +process_decl : + PROCESS_K process_name '(' constant_body ')' ';' + fpar_decl_opt_list + { PROCESS = + new IfProcessEntity($4, + $7, + new IfList<IfState>(1), + new IfList<IfConstant>(1), + new IfList<IfType>(1), + new IfList<IfVariable>(1), + new IfList<IfProcedure>(1), + $2); } + process_component_set + ENDPROCESS_K ';' { $$ = PROCESS; PROCESS = NULL; } +; + +observer_decl : + obs_kind OBSERVER_K process_name ';' + { PROCESS = + new IfObserverEntity((IfObserverEntity::EObsKind)$1, + new IfList<IfState>(1), + new IfList<IfConstant>(1), + new IfList<IfType>(1), + new IfList<IfVariable>(1), + new IfList<IfProcedure>(1), + $3); + } + process_component_set + ENDOBSERVER_K ';' + { + $$ = PROCESS; + PROCESS = NULL; + } +; + +obs_kind : + PURE_K + { $$ = IfObserverEntity::PURE; } +| CUT_K + { $$ = IfObserverEntity::CUT; } +| INTRUSIVE_K + { $$ = IfObserverEntity::INTRUSIVE; } +; +priority_decl : + priority_rule_id ':' process_name '<' process_name + { + PRIORITYRULE = + new IfPriorityRuleEntity( + new IfVariable(IfVariable::FIELD, + IfVariable::PRIVATE, + IfVariable::NOMODE, + IfObject::TYPES[IfBasicType::PID], + NULL, + $3), + new IfVariable(IfVariable::FIELD, + IfVariable::PRIVATE, + IfVariable::NOMODE, + IfObject::TYPES[IfBasicType::PID], + NULL, + $5), + NULL, + $1, + 0 + ); + + } + IF_K priority_expression ';' { + PRIORITYRULE->SetExpression($8); $$ = PRIORITYRULE; PRIORITYRULE = NULL; } +; + +priority_rule_id : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +process_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +process_component_set : + process_component_set process_component { } +| /* empty */ { } +; + +process_component : + constant_decl { PROCESS->GetConstants()->Add($1); } +| type_decl { PROCESS->GetTypes()->Add($1); } +| variable_decl { PROCESS->GetVariables()->Add($1); } +| procedure_decl { PROCESS->GetProcedures()->Add($1); } +| state_decl { PROCESS->GetStates()->Add($1); } +; + +/* +-------------------------------------------------------------------- +System +-------------------------------------------------------------------- +*/ + +system_decl : + SYSTEM_K system_name ';' + { + SYSTEM = + new IfSystemEntity(new IfList<IfProcessEntity>(1), + new IfList<IfPriorityRuleEntity>(1), + new IfList<IfObserverEntity>(1), + new IfList<IfSignalroute>(1), + new IfList<IfSignal>(1), + new IfList<IfResource>(1), + new IfList<IfConstant>(1), + new IfList<IfType>(1), + new IfList<IfVariable>(1), + new IfList<IfProcedure>(1), + $2); + } + system_component_set + ENDSYSTEM_K ';' + { + SYSTEM->CreateSigUnionType(); + } + observer_or_priority_decl_set + { } +; + +system_name : + _IDENTIFIER_ { $$ = strdup(yytext); } +; + +system_component_set : + system_component_set system_component { } +| /* empty */ { } +; + +system_component : + constant_decl { SYSTEM->GetConstants()->Add($1); } +| type_decl { SYSTEM->GetTypes()->Add($1); } +| variable_decl { SYSTEM->GetVariables()->Add($1); } +| procedure_decl { SYSTEM->GetProcedures()->Add($1); } +| resource_decl { SYSTEM->GetResources()->Add($1); } +| signal_decl { SYSTEM->GetSignals()->Add($1); } +| signalroute_decl { SYSTEM->GetSignalroutes()->Add($1); } +| process_decl { SYSTEM->GetProcesses()->Add((IfProcessEntity*)$1); } +; + +observer_or_priority_decl_set : + observer_or_priority_decl_set observer_decl { SYSTEM->GetObservers()->Add((IfObserverEntity*)$2); } +| + observer_or_priority_decl_set priority_section { } +| /* empty */ { } +; + +priority_section : + PRIORITY_SECTION_K + priority_decl_set + END_PRIORITY_SECTION_K ';' { } +; +priority_decl_set : + priority_decl_set priority_decl + { + SYSTEM->GetPriorityRules()->Add((IfPriorityRuleEntity*)$2); + } + | /*empty*/ { } +; + + +/* +-------------------------------------------------------------------- +Misc +-------------------------------------------------------------------- +*/ + +integer : + _INTEGER_ { $$ = atoi(yytext); } +; + +option_set : + option_set option { int i = 0; while ($1[i]) i++; $1[i] = $2; $$ = $1; } +| /* empty */ { $$ = (char**) calloc(16, sizeof(char*)); } +; + +option : + _OPTION_ { $$ = strdup(yytext); } +; + +%% + +IfSystemEntity* Load(FILE* file, FILE** p_pfObservers, int p_nObservers) { + int i; + yyin = file; + + nObservers = p_nObservers; + for(i = 0; i < nObservers; i++) { + hbObservers[i] = yy_create_buffer( p_pfObservers[i], YY_BUF_SIZE); + } + yyparse(); + return SYSTEM; +} diff --git a/src/model/list.C b/src/model/list.C new file mode 100644 index 0000000000000000000000000000000000000000..a9a5629e66c1ff0a134d8cc9a3bdcf76493f4ced --- /dev/null +++ b/src/model/list.C @@ -0,0 +1,206 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of generic lists + * + */ + +template <class C> +C* IfList<C>::Find(const char* Name) const { + C* object = NULL; + for(int i = 0; i < GetCount(); i++) + if (! strcmp(Name, GetAt(i)->GetName())){ + object = GetAt(i); + break; + } + return object; +} + +template <class C> +C* IfList<C>::Find(const C* Object) const { + C* object = NULL; + for(int i = 0; i < GetCount(); i++) + if ( GetAt(i) == Object){ + object = (C*) Object; + break; + } + return object; +} + +template <class C> +int IfList<C>::Position(const C* Object) const { + int pos = -1; + for (int i = 0; i < GetCount(); i++) + if (GetAt(i) == Object){ + pos = i; + break; + } + return pos; +} + +template <class C> +void IfList<C>::Add(const C* Object){ + if (m_iSize == m_iCount){ + m_iSize += m_iGrowth; + m_pObjects = (C**) realloc(m_pObjects, sizeof(C*) * m_iSize); + } + m_pObjects[m_iCount++] = (C*) Object; +} + +template <class C> +void IfList<C>::Add(const IfList<C>* Objects){ + if (m_iCount + Objects->GetCount() > m_iSize){ + m_iSize += Objects->GetCount(); + m_pObjects = (C**) realloc(m_pObjects, sizeof(C*) * m_iSize); + } + for(int i = 0; i < Objects->GetCount(); i++) + m_pObjects[m_iCount++] = Objects->GetAt(i); +} + +template <class C> +void IfList<C>::Remove(const C* Object){ + int i; + for(i = 0; i < GetCount(); i++) + if (GetAt(i) == Object) + break; + if (i < GetCount()) { + if (m_iOwner) + delete Object; + for(i++; i < GetCount(); i++) + m_pObjects[i-1] = m_pObjects[i]; + m_iCount--; + } +} + +template <class C> +void IfList<C>::Push(const C* Object){ + Add(Object); +} + +template <class C> +C* IfList<C>::Top(int i) const { + return m_pObjects[m_iCount-1+i]; +} + +template <class C> +void IfList<C>::Pop() { + m_iCount--; +} + + +template <class C> +void IfList<C>::DumpName(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const { + if (GetCount()) + fprintf(file, "%s", Begin); + for(int i = 0; i < GetCount(); i++){ + fprintf(file, "%s", GetAt(i)->GetName()); + fprintf(file, "%s", i == GetCount() - 1 ? End : Separator); + } +} + +template <class C> +void IfList<C>::Dump(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const { + if (GetCount()) + fprintf(file, "%s", Begin); + for(int i = 0; i < GetCount(); i++){ + GetAt(i)->Dump(file); + fprintf(file,"%s", i == GetCount() - 1 ? End : Separator); + } +} + +template <class C> +int IfList<C>::GetFlag(const unsigned Flag) const { + int flag = 0; + for(int i = 0; i < GetCount(); i++) + flag |= GetAt(i)->GetFlag(Flag); + return flag; +} + +template <class C> +void IfList<C>::SetIndex(int* Index) const { + for(int i = 0; i < GetCount(); i++) + GetAt(i)->SetIndex(Index); +} + +template <class C> +int IfList<C>::Compile() const { + int ok = 1; + for(int i = 0; i < GetCount(); i++) + ok &= GetAt(i)->Compile(); + return ok; +} + +template <class C> +void IfList<C>::Code(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const { + if (GetCount()) + fprintf(file, "%s", Begin); + for(int i = 0; i < GetCount(); i++){ + GetAt(i)->Code(file); + fprintf(file,"%s", i == GetCount() - 1 ? End : Separator); + } +} + +template <class C> +IfList<C>::IfList(const int Owner, const int Growth){ + m_iOwner = Owner ? 1 : 0; + m_iCount = 0; + m_iGrowth = (Growth > 0) ? Growth : 4; + m_iSize = m_iGrowth; + m_pObjects = (C**) malloc(sizeof(C*) * m_iSize); +} + +template <class C> +IfList<C>::~IfList(){ + if (m_iOwner) + for(int i = 0; i < m_iCount; i++) + delete m_pObjects[i]; + free(m_pObjects); +} diff --git a/src/model/list.h b/src/model/list.h new file mode 100644 index 0000000000000000000000000000000000000000..de578d8118f20506d91eb73a827f9113ecb77071 --- /dev/null +++ b/src/model/list.h @@ -0,0 +1,103 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * generic list interface + * + */ + +template <class C> class IfList { + + public: + IfList(int Owner = 0, + int Growth = 4); + ~IfList(); + + public: + inline int GetGrowth() const { return m_iGrowth; } + inline int IsOwner() const { return m_iOwner; } + inline int GetSize() const { return m_iSize; } + inline int GetCount() const { return m_iCount; } + inline C* GetAt(int i) const { return m_pObjects[i]; } + inline void SetAt(int i, C* Object) { m_pObjects[i] = Object; } + inline C* operator[](int i) const { return m_pObjects[i]; } + + public: + C* Find(const char* Name) const; + C* Find(const C* Object) const; + int Position(const C* Object) const; + void Add(const C* Object); + void Add(const IfList<C>* List); + void Remove(const C* Object); + + public: + void Push(const C* Object); + C* Top(int i = 0) const; + void Pop(); + + public: + void DumpName(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const; + void Dump(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const; + + void Code(FILE*, + const char* Begin, + const char* Separator, + const char* End) const; + + int GetFlag(const unsigned Flag) const; + void SetIndex(int* Index) const; + int Compile() const; + + + protected: + int m_iGrowth; + int m_iOwner; + int m_iSize; + int m_iCount; + C** m_pObjects; + +}; diff --git a/src/model/list.i b/src/model/list.i new file mode 100644 index 0000000000000000000000000000000000000000..a9a5629e66c1ff0a134d8cc9a3bdcf76493f4ced --- /dev/null +++ b/src/model/list.i @@ -0,0 +1,206 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of generic lists + * + */ + +template <class C> +C* IfList<C>::Find(const char* Name) const { + C* object = NULL; + for(int i = 0; i < GetCount(); i++) + if (! strcmp(Name, GetAt(i)->GetName())){ + object = GetAt(i); + break; + } + return object; +} + +template <class C> +C* IfList<C>::Find(const C* Object) const { + C* object = NULL; + for(int i = 0; i < GetCount(); i++) + if ( GetAt(i) == Object){ + object = (C*) Object; + break; + } + return object; +} + +template <class C> +int IfList<C>::Position(const C* Object) const { + int pos = -1; + for (int i = 0; i < GetCount(); i++) + if (GetAt(i) == Object){ + pos = i; + break; + } + return pos; +} + +template <class C> +void IfList<C>::Add(const C* Object){ + if (m_iSize == m_iCount){ + m_iSize += m_iGrowth; + m_pObjects = (C**) realloc(m_pObjects, sizeof(C*) * m_iSize); + } + m_pObjects[m_iCount++] = (C*) Object; +} + +template <class C> +void IfList<C>::Add(const IfList<C>* Objects){ + if (m_iCount + Objects->GetCount() > m_iSize){ + m_iSize += Objects->GetCount(); + m_pObjects = (C**) realloc(m_pObjects, sizeof(C*) * m_iSize); + } + for(int i = 0; i < Objects->GetCount(); i++) + m_pObjects[m_iCount++] = Objects->GetAt(i); +} + +template <class C> +void IfList<C>::Remove(const C* Object){ + int i; + for(i = 0; i < GetCount(); i++) + if (GetAt(i) == Object) + break; + if (i < GetCount()) { + if (m_iOwner) + delete Object; + for(i++; i < GetCount(); i++) + m_pObjects[i-1] = m_pObjects[i]; + m_iCount--; + } +} + +template <class C> +void IfList<C>::Push(const C* Object){ + Add(Object); +} + +template <class C> +C* IfList<C>::Top(int i) const { + return m_pObjects[m_iCount-1+i]; +} + +template <class C> +void IfList<C>::Pop() { + m_iCount--; +} + + +template <class C> +void IfList<C>::DumpName(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const { + if (GetCount()) + fprintf(file, "%s", Begin); + for(int i = 0; i < GetCount(); i++){ + fprintf(file, "%s", GetAt(i)->GetName()); + fprintf(file, "%s", i == GetCount() - 1 ? End : Separator); + } +} + +template <class C> +void IfList<C>::Dump(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const { + if (GetCount()) + fprintf(file, "%s", Begin); + for(int i = 0; i < GetCount(); i++){ + GetAt(i)->Dump(file); + fprintf(file,"%s", i == GetCount() - 1 ? End : Separator); + } +} + +template <class C> +int IfList<C>::GetFlag(const unsigned Flag) const { + int flag = 0; + for(int i = 0; i < GetCount(); i++) + flag |= GetAt(i)->GetFlag(Flag); + return flag; +} + +template <class C> +void IfList<C>::SetIndex(int* Index) const { + for(int i = 0; i < GetCount(); i++) + GetAt(i)->SetIndex(Index); +} + +template <class C> +int IfList<C>::Compile() const { + int ok = 1; + for(int i = 0; i < GetCount(); i++) + ok &= GetAt(i)->Compile(); + return ok; +} + +template <class C> +void IfList<C>::Code(FILE* file, + const char* Begin, + const char* Separator, + const char* End) const { + if (GetCount()) + fprintf(file, "%s", Begin); + for(int i = 0; i < GetCount(); i++){ + GetAt(i)->Code(file); + fprintf(file,"%s", i == GetCount() - 1 ? End : Separator); + } +} + +template <class C> +IfList<C>::IfList(const int Owner, const int Growth){ + m_iOwner = Owner ? 1 : 0; + m_iCount = 0; + m_iGrowth = (Growth > 0) ? Growth : 4; + m_iSize = m_iGrowth; + m_pObjects = (C**) malloc(sizeof(C*) * m_iSize); +} + +template <class C> +IfList<C>::~IfList(){ + if (m_iOwner) + for(int i = 0; i < m_iCount; i++) + delete m_pObjects[i]; + free(m_pObjects); +} diff --git a/src/model/model.C b/src/model/model.C new file mode 100644 index 0000000000000000000000000000000000000000..d3438a729e683c236805c31b8e46d0cc579420ce --- /dev/null +++ b/src/model/model.C @@ -0,0 +1,76 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * IF model utilities + * + */ + +#include "model.h" + +char* indent(const int depth) { + static char space[256]; + int k = 2 * depth / 8; + int l = 2 * depth % 8; + int i = 0; + for(; i < k; i++) + space[i] = '\t'; + for(; i < l; i++) + space[i] = ' '; + space[i] = '\0'; + return space; +} + +char* filename(const char* basename, + const char* suffix, + const char* suffxi) { + static char name[256]; + strcpy(name, basename); + if (suffix) { + int k = strlen(basename) - strlen(suffix); + if (strcmp(name + k, suffix) == 0) + name[k] = '\0'; + } + if (suffxi) { + strcat(name, suffxi); + } + return name; +} diff --git a/src/model/model.h b/src/model/model.h new file mode 100644 index 0000000000000000000000000000000000000000..f140db1467e96ddef6bea3bcb7b55c68c535cb1b --- /dev/null +++ b/src/model/model.h @@ -0,0 +1,109 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * IF model interface + * + */ + +#ifndef MODEL_H +#define MODEL_H + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +template <class C> class IfList; + +class IfObject; +class IfConstant; +class IfFunction; +class IfType; + class IfBasicType; +class IfVariable; +class IfExpression; +class IfConstraint; +class IfResource; +class IfSignal; +class IfSignalroute; +class IfAction; +class IfStatement; + class IfBasicStatement; + class IfBlockStatement; +class IfTransition; +class IfState; +class IfEntity; + class IfAutomatonEntity; + class IfProcessEntity; + class IfObserverEntity; + class IfPriorityRuleEntity; + class IfMacroEntity; + +#include "list.h" +#include "list.i" + +#include "object.h" +#include "constant.h" +#include "type.h" +#include "variable.h" +#include "expression.h" +#include "constraint.h" +#include "resource.h" +#include "signal.h" +#include "signalroute.h" +#include "procedure.h" +#include "action.h" +#include "statement.h" +#include "transition.h" +#include "state.h" +#include "entity.h" +#include "priorityrule.h" + +IfSystemEntity* Load(FILE* file, FILE** p_pfObservers, int p_nObservers); + +char* indent(const int); +char* filename(const char*, const char* = NULL, const char* = NULL); + +/* various options */ +extern int opt_m4codegen; /* controls model instrumentation for code generation (esp. for observers) */ + +#endif diff --git a/src/model/object.C b/src/model/object.C new file mode 100644 index 0000000000000000000000000000000000000000..c9db09fab964b19cfb02d6655a7a4360eb17f788 --- /dev/null +++ b/src/model/object.C @@ -0,0 +1,114 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of abstract objects + * + */ + +#include "model.h" + +IfObject::IfObject(char* Name, + unsigned Flags) { + extern int yylineno; + + m_pName = (char*) Name; + m_uLinenum = (unsigned) yylineno; + m_uFlags = Flags; + m_iIndex = -1; + + m_pData = NULL; +} + +IfObject::~IfObject() { + if (m_pName) free(m_pName); +} + +void IfObject::Dump(FILE*) const { + // pure virtual +} + + +void IfObject::Protest(const char* Message) const { + fprintf(stderr, "line %d : %s %s: %s!\n", + m_uLinenum, m_pName ? m_pName : "{anonymous}", + GetClass(), Message); +} + +int IfObject::Compile() { + PreCompile(); + PostCompile(); + return GetFlag(CORRECT); +} + +void IfObject::PreCompile() { + SetFlag(COMPILED, 0); + SetFlag(CORRECT, 1); + CONTEXT.Push(this); +} + +void IfObject::PostCompile() { + CONTEXT.Pop(); + if (!GetFlag(CORRECT)) + Protest("compile failed"); + SetFlag(COMPILED, 1); +} + +void IfObject::Code(FILE*) const { + // pure virtual +} + +void IfObject::Initialize() { + TYPES.Add(new IfBasicType(IfBasicType::BOOLEAN, strdup("boolean"))); + TYPES.Add(new IfBasicType(IfBasicType::INTEGER, strdup("integer"))); + TYPES.Add(new IfBasicType(IfBasicType::REAL, strdup("real"))); + TYPES.Add(new IfBasicType(IfBasicType::CLOCK, strdup("clock"), TIMED)); + TYPES.Add(new IfBasicType(IfBasicType::PID, strdup("pid"))); + TYPES.Add(new IfBasicType(IfBasicType::VOID, strdup("void"))); +} + +unsigned IfObject::DEPTH = 0; + +IfList<IfBasicType> IfObject::TYPES(1); + +IfList<IfObject> IfObject::CONTEXT; + +unsigned IfObject::TRANSFORM = 0; diff --git a/src/model/object.h b/src/model/object.h new file mode 100644 index 0000000000000000000000000000000000000000..f0b5dc985b281edc6c41a1b1f8935f588b667e5f --- /dev/null +++ b/src/model/object.h @@ -0,0 +1,128 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract object interface + * + */ + +class IfObject { + + public: + static void Initialize(); + + static IfList<IfBasicType> TYPES; + + public: + IfObject(char* Name = NULL, + unsigned Flags = 0); + virtual ~IfObject(); + + public: + inline char* GetName() const + { return m_pName; } + inline int GetLinenum() const + { return m_uLinenum; } + inline int GetFlag(const unsigned Flag) const + { return (m_uFlags & Flag) ? 1 : 0; } + inline int GetIndex() const + { return m_iIndex; } + inline void* GetData() const + { return m_pData; } + + public: + inline void SetName(char* Name) + { m_pName = Name; } + inline void SetLinenum(const int Linenum) + { m_uLinenum = Linenum; } + inline void SetFlag(const unsigned Flag, + const int Value) + { if (Value) m_uFlags |= Flag; else m_uFlags &= ~Flag; } + virtual void SetIndex(int* Index) + { m_iIndex = (*Index)++; } + virtual void SetData(void* Data) + { m_pData = Data; } + + public: + virtual const char* GetClass() const + { return "object"; } + virtual int IsExpression() const + { return 0; } + virtual int IsConstraint() const + { return 0; } + virtual int IsAction() const + { return 0; } + virtual int IsState() const + { return 0; } + virtual int IsEntity() const + { return 0; } + + public: + virtual void Dump(FILE* file) const; + protected: + static unsigned DEPTH; + + public: + enum CFlag { COMPILED = 2, CORRECT = 4, TIMED = 8 }; + + virtual void Protest(const char* Message) const; + virtual int Compile(); + virtual void PreCompile(); + virtual void PostCompile(); + protected: + static IfList<IfObject> CONTEXT; + + public: + enum TFlag { XSCOPE = 2 }; + static unsigned TRANSFORM; + + public: + virtual void Code(FILE* file) const; + + protected: + char* m_pName; + unsigned m_uFlags; + unsigned m_uLinenum; + int m_iIndex; + + void* m_pData; // user data + +}; diff --git a/src/model/priorityrule.C b/src/model/priorityrule.C new file mode 100644 index 0000000000000000000000000000000000000000..7d3f6db6342bcdcc9eaefcb7d86b9c9ac173d569 --- /dev/null +++ b/src/model/priorityrule.C @@ -0,0 +1,111 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of priority rules + * + */ + +#include "model.h" + +/* + * + * priority rule implementation + * + */ + + +IfPriorityRuleEntity::IfPriorityRuleEntity(IfVariable* var1, + IfVariable* var2, + IfExpression* condition, + char* Name, + unsigned int Flags) + : IfEntity(NULL,NULL,NULL,NULL,Name, Flags){ + + m_pProcessVar1=var1; + m_pProcessVar2=var2; + m_pExpression = condition; + +} + +IfPriorityRuleEntity::~IfPriorityRuleEntity(){ + delete m_pExpression; + delete m_pProcessVar1; + delete m_pProcessVar2; +} + +void IfPriorityRuleEntity::Dump(FILE* file) const { + fprintf(file, "%s : ",m_pName); + fprintf(file,"%s < %s", m_pProcessVar1->GetName(),m_pProcessVar2->GetName()); + fprintf(file," if "); + m_pExpression->Dump(file); + fprintf(file,";"); +} + +void IfPriorityRuleEntity::PreCompile(){ + IfObject::PreCompile(); + + int ok = 1; + ok &= m_pProcessVar1->Compile(); + ok &= m_pProcessVar2->Compile(); + ok &= m_pExpression->Compile(); + SetFlag(CORRECT, ok); +} + +void IfPriorityRuleEntity::Code(FILE* file) const { + CONTEXT.Push(this); + fprintf(file,"pushdef(`imp0rt',`((instance_name($1)*) q->get($2))->$3()')\n"); + fprintf(file,"pushdef(`getStateNo',`((instance_name($1)*) q->get($2))->GetSP()')\n"); + + fprintf(file,"pushdef(`if_clock_active', `X->getTime()->active($1)')\n"); + fprintf(file,"pushdef(`if_clock_timeval',`X->getTime()->timeval($1)')\n"); + fprintf(file,"code(priority_rule,"); + m_pProcessVar1->Code(file); + fprintf(file,","); + m_pProcessVar2->Code(file); + fprintf(file,","); + m_pExpression->Code(file); + fprintf(file,",%d)",GetIndex()); + fprintf(file,"popdef(`imp0rt')\npopdef(`getStateNo')\npopdef(`if_clock_active')\npopdef(`if_clock_timeval')\n"); + CONTEXT.Pop(); +} + + diff --git a/src/model/priorityrule.h b/src/model/priorityrule.h new file mode 100644 index 0000000000000000000000000000000000000000..5fc49580b105545a90829b180b267d18f11d55cb --- /dev/null +++ b/src/model/priorityrule.h @@ -0,0 +1,77 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * priority rule interface + * + */ + +class IfPriorityRuleEntity : public IfEntity { + +public: + IfPriorityRuleEntity(IfVariable* Var1, + IfVariable* Var2, + IfExpression* Condition, + char* Name, + unsigned int FLAG); + virtual ~IfPriorityRuleEntity(); + +public: + inline IfExpression* GetExpression() const { return m_pExpression; } + inline IfVariable* GetProcessVar1() const { return m_pProcessVar1; } + inline IfVariable* GetProcessVar2() const { return m_pProcessVar2; } + inline void SetExpression(IfExpression* Condition) { m_pExpression = Condition; } + inline void SetProcessVar1(IfVariable* var) { m_pProcessVar1 = var; } + inline void SetProcessVar2(IfVariable* var) { m_pProcessVar2 = var; } + +public: + virtual int IsPriority() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + +protected: + IfVariable* m_pProcessVar1; + IfVariable* m_pProcessVar2; + IfExpression* m_pExpression; + +}; + diff --git a/src/model/procedure.C b/src/model/procedure.C new file mode 100644 index 0000000000000000000000000000000000000000..4d28bcaacc134524b2a9c83b91724132212635b6 --- /dev/null +++ b/src/model/procedure.C @@ -0,0 +1,121 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of abstract functions + * + */ + +#include "model.h" + +IfProcedure::IfProcedure(IfList<IfVariable>* Parameters, + IfType* Return, + char* Body, + char* Name, + unsigned Flags) + : IfObject(Name, Flags) { + m_pParameters = Parameters; + m_pReturn = Return; + m_pBody = Body; + m_pEntity = NULL; +} + +IfProcedure::~IfProcedure() { + delete m_pParameters; + if (m_pBody) free(m_pBody); +} + +void IfProcedure::Dump(FILE* file) const { + fprintf(file, "procedure %s;\n", m_pName); + if (m_pParameters->GetCount()) + m_pParameters->Dump(file, " fpar ", ", ", ";\n"); + if (m_pReturn) + fprintf(file, " returns %s;\n", m_pReturn->GetName()); + if (m_pBody) + fprintf(file, "%s", m_pBody); + fprintf(file, "\nendprocedure;\n"); +} + +void IfProcedure::PreCompile() { + IfObject::PreCompile(); + + int ok = 1, tm = 0; + + ok &= m_pParameters->Compile(); + + for(int i = 0; i < m_pParameters->GetCount(); i++) + tm |= m_pParameters->GetAt(i)->GetType()->GetFlag(TIMED); + if (tm) + Protest("timed parameters"); + + if (m_pReturn) + tm |= m_pReturn->GetFlag(TIMED); + + m_pEntity = (IfEntity*) CONTEXT.Top(-1); + + SetFlag(CORRECT, ok && !tm); + +} + +void IfProcedure::Code(FILE* file) const { + fprintf(file, "code(procedure,%s,%s,%d,(", + m_pName, m_pEntity->GetName(), m_uLinenum); + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfVariable* variable = m_pParameters->GetAt(i); + if (variable->IsInout() || variable->IsOut()) + fprintf(file, "&"); + fprintf(file, "%s,%s", variable->GetName(), + variable->GetType()->GetName()); + if (i < m_pParameters->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "),"); + if (m_pReturn) + fprintf(file, "%s", m_pReturn->GetName()); + fprintf(file, ","); + if (m_pBody) { // {# ... #} + int len = strlen(m_pBody); + m_pBody[len - 2] = '\0'; + fprintf(file, "\n\t`%s'", m_pBody+2); + m_pBody[len - 2] = '#'; + } + fprintf(file, ")"); +} diff --git a/src/model/procedure.h b/src/model/procedure.h new file mode 100644 index 0000000000000000000000000000000000000000..9989fcaf7293604bd659cd39feef367b859cdc73 --- /dev/null +++ b/src/model/procedure.h @@ -0,0 +1,75 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * procedure interface + * + */ + +class IfProcedure : public IfObject { + + public: + IfProcedure(IfList<IfVariable>* Parameters, + IfType* Return, + char* Body, + char* Name, + unsigned Flags = 0); + virtual ~IfProcedure(); + + public: + inline IfList<IfVariable>* GetParameters() const { return m_pParameters; } + inline IfType* GetReturn() const { return m_pReturn; } + inline char* GetBody() const { return m_pBody; } + inline IfEntity* GetEntity() const { return m_pEntity; } + + public: + virtual const char* GetClass() const { return "procedure"; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfList<IfVariable>* m_pParameters; + IfType* m_pReturn; + char* m_pBody; + + IfEntity* m_pEntity; +}; diff --git a/src/model/resource.C b/src/model/resource.C new file mode 100644 index 0000000000000000000000000000000000000000..b4a3d49a52f6fd3db56620439badb29d9943b435 --- /dev/null +++ b/src/model/resource.C @@ -0,0 +1,66 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of resources + * + */ + +#include "model.h" + +IfResource::IfResource(char* Name, unsigned Flags) : + IfObject(Name, Flags) { +} + +IfResource::~IfResource() { +} + +void IfResource::Dump(FILE* file) const { + fprintf(file, "resource %s;", m_pName); +} + +void IfResource::PreCompile() { + IfObject::PreCompile(); +} + +void IfResource::Code(FILE* file) const { + fprintf(file, "code(resource,%s,%d)", m_pName, m_iIndex); +} diff --git a/src/model/resource.h b/src/model/resource.h new file mode 100644 index 0000000000000000000000000000000000000000..e522537edfd58762630b72645dcf43a1ede22239 --- /dev/null +++ b/src/model/resource.h @@ -0,0 +1,60 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * resource interface + * + */ + +class IfResource : public IfObject { + + public: + IfResource(char* Name, + unsigned Flags = 0); + virtual ~IfResource(); + + public: + virtual const char* GetClass() const { return "resource"; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + +}; diff --git a/src/model/signal.C b/src/model/signal.C new file mode 100644 index 0000000000000000000000000000000000000000..4e552a668a5e7064f26ebfd258d6006befa6c117 --- /dev/null +++ b/src/model/signal.C @@ -0,0 +1,88 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of signals + * + */ + +#include "model.h" + +IfSignal::IfSignal(IfList<IfType>* Parameters, + char* Name, + unsigned Flags) : + IfObject(Name, Flags) { + m_pParameters = Parameters; +} + +IfSignal::~IfSignal() { + delete m_pParameters; +} + +void IfSignal::PreCompile() { + IfObject::PreCompile(); + + int tm = 0; + for(int i = 0; i < m_pParameters->GetCount(); i++) + tm |= m_pParameters->GetAt(i)->GetFlag(TIMED); + if (tm) { + SetFlag(CORRECT, 0); + Protest("timed parameters"); + } +} + +void IfSignal::Dump(FILE* file) const { + fprintf(file, "signal %s(", m_pName); + m_pParameters->DumpName(file, "", ", ", ""); + fprintf(file, ");"); +} + +void IfSignal::Code(FILE* file) const { + fprintf(file, "code(message,%s,%d,\n\t(", + m_pName, m_iIndex); + for(int i =0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pParameters->GetAt(i); + fprintf(file, "p%d,%s", i+1, type->GetName()); + if (i < m_pParameters->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "))"); +} diff --git a/src/model/signal.h b/src/model/signal.h new file mode 100644 index 0000000000000000000000000000000000000000..a4e0c51817f041b0ea73b02cfd8be436723b5eb4 --- /dev/null +++ b/src/model/signal.h @@ -0,0 +1,69 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * signal interface + * + */ + +class IfSignal : public IfObject { + public: + enum EFlag { OBSERVED = 1024 }; + + public: + IfSignal(IfList<IfType>* Parameters, + char* Name, + unsigned Flags = 0); + virtual ~IfSignal(); + + public: + inline IfList<IfType>* GetParameters() const { return m_pParameters; } + + public: + virtual const char* GetClass() const { return "signal"; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfList<IfType>* m_pParameters; + +}; diff --git a/src/model/signalroute.C b/src/model/signalroute.C new file mode 100644 index 0000000000000000000000000000000000000000..0749b1a40949089d09a9b0a6144109084defb852 --- /dev/null +++ b/src/model/signalroute.C @@ -0,0 +1,179 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +/* + * + * signalroute.C 1.5 [06/17/01] + * + */ + +/* + * + * implementation of signalroutes + * + */ + +#include "model.h" + +IfSignalroute::IfSignalroute(IfConstant* Instances, + char* Option[], + char* FromName, + char* ToName, + IfList<IfSignal>* Signals, + char* Name, + unsigned Flags) : + IfObject(Name, Flags) { + m_pInstances = Instances; + m_uOptions = FIFO | RELIABLE | PEER | URGENT; + m_pFromName = FromName; + m_pFrom = NULL; + m_pToName = ToName; + m_pTo = NULL; + m_pSignals = Signals; + m_iLower = m_iUpper = -1; + m_fProba = 0; + + for(int i = 0; Option[i]; i++) { + int l = 0, u = 0; + float proba = 0; + if (!strcmp(Option[i], "#fifo")) + m_uOptions = (m_uOptions & 0xFFFFFF00) | FIFO; + else if (!strcmp(Option[i], "#multiset")) + m_uOptions = (m_uOptions & 0xFFFFFF00) | MULTISET; + else if ( sscanf(Option[i], "#lossy[%f]", &proba) == 1) { + m_uOptions = (m_uOptions & 0xFFFF00FF) | LOSSY; + m_fProba = proba; + } + else if (!strcmp(Option[i], "#lossy")) { + m_uOptions = (m_uOptions & 0xFFFF00FF) | LOSSY; + m_fProba = 0.01; /* default loss probability */ + } + else if (!strcmp(Option[i], "#reliable")) + m_uOptions = (m_uOptions & 0xFFFF00FF) | RELIABLE; + else if (!strcmp(Option[i], "#peer")) + m_uOptions = (m_uOptions & 0xFF00FFFF) | PEER; + else if (!strcmp(Option[i], "#multicast")) + m_uOptions = (m_uOptions & 0xFF00FFFF) | MULTICAST; + else if (!strcmp(Option[i], "#unicast")) + m_uOptions = (m_uOptions & 0xFF00FFFF) | UNICAST; + else if (!strcmp(Option[i], "#urgent")) + m_uOptions = (m_uOptions & 0x00FFFFFF) | URGENT; + else if ( sscanf(Option[i], "#delay[%d,%d]", &l, &u) == 2) { + m_uOptions = (m_uOptions & 0x00FFFFFF) | DELAY; + m_iLower = l; m_iUpper = u; + } + else if ( sscanf(Option[i], "#rate[%d,%d]", &l, &u) == 2) { + m_uOptions = (m_uOptions & 0x00FFFFFF) | RATE; + m_iLower = l; m_iUpper = u; + } + } +} + +IfSignalroute::~IfSignalroute() { + delete m_pInstances; + free(m_pFromName); + free(m_pToName); + delete m_pSignals; +} + +void IfSignalroute::Dump(FILE* file) const { + fprintf(file, "signalroute %s(", m_pName); + m_pInstances->DumpNameOrValue(file); + fprintf(file, ")"); + + if (Is(MULTISET)) fprintf(file, " #multiset"); + if (Is(LOSSY)) fprintf(file, " #lossy[%.6f]", m_fProba); + if (Is(MULTICAST)) fprintf(file, " #multicast"); + if (Is(UNICAST)) fprintf(file, " #unicast"); + if (Is(DELAY)) fprintf(file, " #delay[%d,%d]", m_iLower, m_iUpper); + if (Is(RATE)) fprintf(file, " #rate[%d,%d]", m_iLower, m_iUpper); + + fprintf(file, "\n from %s to %s\n", m_pFromName, m_pToName); + m_pSignals->DumpName(file, " with ", ",\n", ""); + fprintf(file, ";"); +} + +void IfSignalroute::PreCompile() { + IfObject::PreCompile(); + IfSystemEntity* sys = (IfSystemEntity*) CONTEXT[0]; + + int ok = 1; + + ok &= m_pInstances->Compile(); + ok &= m_pInstances->GetBase()->IsInteger(); + + if (strcmp(m_pFromName,"env")) { + m_pFrom = sys->GetProcesses()->Find(m_pFromName); + if (m_pFrom == NULL) { + Protest("undefined source"); ok = 0; + } + } + if (strcmp(m_pToName,"env")) { + m_pTo = sys->GetProcesses()->Find(m_pToName); + if (m_pTo == NULL) { + Protest("undefined destination"); ok = 0; + } + } + if (Is(DELAY) || Is(RATE)) { + if (m_iLower < 0 || + m_iUpper < 0 || m_iLower > m_iUpper) { + Protest("undefined delay"); ok = 0; + } + } + if (Is(LOSSY)) { + if (m_fProba < 0 || 1 < m_fProba) { + Protest("probability outside bounds"); ok = 0; + } + } + + SetFlag(CORRECT, ok); +} + +void IfSignalroute::Code(FILE* file) const { + if (m_pFrom == NULL || m_pTo == NULL) + return; + fprintf(file, "code(buffer,%s,%d,%s,%s,%s,%s|%s|%s|%s,%d,%d,%.6f)", + m_pName, m_iIndex, Is(FIFO) ? "Fifo" : "Multiset", + m_pFrom->GetName(), m_pTo->GetName(), + Is(FIFO) ? "FIFO" : "MULTISET", + Is(RELIABLE) ? "RELIABLE" : "LOSSY", + Is(PEER) ? "PEER" : Is(MULTICAST) ? "MULTICAST" : "UNICAST", + Is(URGENT) ? "URGENT" : Is(DELAY) ? "DELAY" : "RATE", + m_iLower, m_iUpper, m_fProba); +} diff --git a/src/model/signalroute.h b/src/model/signalroute.h new file mode 100644 index 0000000000000000000000000000000000000000..1d989f41bfefea231426b9cbd0d1e4672d30f3d3 --- /dev/null +++ b/src/model/signalroute.h @@ -0,0 +1,110 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ +/* + * + * signalroute.h 1.5 [06/17/01] + * + */ + +/* + * + * signalroute interface + * + */ + +class IfSignalroute : public IfObject { + + public: + enum { + FIFO = 0x00000001, // queueing policies + MULTISET = 0x00000002, + + RELIABLE = 0x00000100, // reliability + LOSSY = 0x00000200, + + PEER = 0x00010000, // dispacthing policies + MULTICAST = 0x00020000, + UNICAST = 0x00040000, + + URGENT = 0x01000000, // delaying modes + DELAY = 0x02000000, + RATE = 0x04000000 + }; + + public: + IfSignalroute(IfConstant* Instances, + char* Option[], + char* FromName, + char* ToName, + IfList<IfSignal>* Signals, + char* Name, + unsigned Flags = 0); + virtual ~IfSignalroute(); + + public: + inline IfConstant* GetInstances() const { return m_pInstances; } + inline IfProcessEntity* GetFrom() const { return m_pFrom; } + inline IfProcessEntity* GetTo() const { return m_pTo; } + inline IfList<IfSignal>* GetSignals() const { return m_pSignals; } + inline int Is(const unsigned option) const { return m_uOptions & option; } + inline int GetLower() const { return m_iLower; } + inline int GetUpper() const { return m_iUpper; } + + public: + virtual const char* GetClass() const { return "signalroute"; } + + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfConstant* m_pInstances; + unsigned m_uOptions; + IfProcessEntity* m_pFrom; + IfProcessEntity* m_pTo; + IfList<IfSignal>* m_pSignals; + int m_iLower; + int m_iUpper; + double m_fProba; + + char* m_pFromName; + char* m_pToName; + +}; diff --git a/src/model/state.C b/src/model/state.C new file mode 100644 index 0000000000000000000000000000000000000000..203541ded76ef302e9558a026fffa0955f58fc87 --- /dev/null +++ b/src/model/state.C @@ -0,0 +1,373 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of states + * + */ + +#include "model.h" + +IfState::IfState(IfConstraint* Tpc, + IfList<IfSignal>* Saves, + IfList<IfTransition>* Transitions, + IfList<IfState>* States, + char* Option[], + char* Name, + unsigned Flags) : + IfObject(Name, Flags) { + m_pTpc = Tpc; + m_pSaves = Saves; + m_pOutTransitions = Transitions; + m_pStates = States; + m_iSuccess = 0; + m_iError = 0; + + SetFlag(STABLE, 1); + for(int i = 0; Option[i]; i++) { + if (!strcmp(Option[i], "#success")) m_iSuccess = 1; + if (!strcmp(Option[i], "#error")) m_iError = 1; + if (!strcmp(Option[i], "#concurrent")) SetFlag(CONCURRENT, 1); + if (!strcmp(Option[i], "#unstable")) SetFlag(STABLE, 0); + if (!strcmp(Option[i], "#start")) SetFlag(START, 1); + } + + m_pProcess = NULL; + m_pInTransitions = new IfList<IfTransition>(0); + m_pParent = NULL; + m_pEntry = NULL; + m_pInputs = new IfList<IfSignal>(0); + m_iInputNone = 0; +} + +IfState::~IfState() { + if (m_pTpc) delete m_pTpc; + delete m_pSaves; + delete m_pOutTransitions; + delete m_pStates; + delete m_pInTransitions; + delete m_pInputs; +} + +IfState* IfState::Find(const char* Name) const { + IfState* state = NULL; + if (!strcmp(m_pName, Name)) + state = (IfState*) this; + for(int i = 0; i < m_pStates->GetCount() && !state; i++) + state = m_pStates->GetAt(i)->Find(Name); + return state; +} + +void IfState::Dump(FILE* file) const { + fprintf(file, "%sstate %s%s%s%s%s%s;\n", indent(DEPTH), m_pName, + IsStart() ? " #start " : "", + !IsStable() ? " #unstable " : "", + IsConcurrent() ? " #concurrent " : "", + m_iSuccess ? " #success " : "", + m_iError ? " #error " : ""); + if (m_pTpc) { + fprintf(file, "%stpc ", indent(DEPTH+1)); + m_pTpc->Dump(file); + fprintf(file, ";\n"); + } + if (m_pSaves->GetCount()) { + fprintf(file, "%ssave ", indent(DEPTH+1)); + m_pSaves->DumpName(file, "", ", ", ""); + fprintf(file, ";\n"); + } + DEPTH++; + m_pOutTransitions->Dump(file, "","\n","\n"); + m_pStates->Dump(file, "","\n","\n"); + DEPTH--; + fprintf(file, "%sendstate;", indent(DEPTH)); +} + +void IfState::PreCompile() { + IfObject::PreCompile(); + + int ok = 1, index = 0; + + // IfObject* parent = CONTEXT.Top(-1); CS: parent is now m_pParent + // if (!strcmp(parent->GetClass(),"state")) + // m_pParent = (IfState*) parent; + m_pProcess = (IfProcessEntity*) CONTEXT[1]; + + + if (m_pTpc) { + //ok &= m_pTpc->Compile(); CS: old bug? + Protest("tpc's are not supported"); + } + if (!IsStable() && IsStart()) { + Protest("wrong unstable start state, ignored"); + SetFlag(STABLE, 1); + } + if (!IsStable() && IsConcurrent()) { + Protest("wrong unstable concurrent state, ignored"); + SetFlag(STABLE, 1); + } + if (!IsStable() && m_pStates->GetCount()) { + Protest("wrong unstable state with substates, ignored"); + SetFlag(STABLE, 1); + } + if (!IsStable() && m_pParent != NULL && m_pParent->IsConcurrent()) { + Protest("wrong unstable state in concurrent state, ignored"); + SetFlag(STABLE, 1); + } + if (IsConcurrent() && m_pStates->GetCount() <= 1) { + Protest("few states in concurrent state, ignored"); + SetFlag(CONCURRENT, 0); + } + if (IsConcurrent() && m_pParent != NULL && m_pParent->IsConcurrent()) { + Protest("nested concurrent states"); ok = 0; + } + + if ((m_pParent == NULL || m_pParent->IsConcurrent()) && !IsConcurrent()) { + SetFlag(CONTROL, 1); + m_pProcess->GetControl()->Add(this); + } + + // get input signals + for(int i = 0; i < m_pOutTransitions->GetCount(); i++) { + IfTransition* transition = m_pOutTransitions->GetAt(i); + IfAction* input = transition->GetInput(); + if (input && input->IsInput()) { + IfSignal* signal = ((IfInputAction*) input)->GetSignal(); + if (m_pInputs->Find(signal) == NULL) + m_pInputs->Add(signal); + } + else + m_iInputNone = 1; + } + + if (IsStable()) { + SetFlag(TNONE, m_iInputNone || + (m_pParent ? m_pParent->GetFlag(TNONE) : 0)); + SetFlag(TSIG, m_pInputs->GetCount() || + (m_pParent ? m_pParent->GetFlag(TSIG) : 0)); + } + else { + SetFlag(TNONE, m_iInputNone); + SetFlag(TSIG, m_pInputs->GetCount()); + } + + ok &= m_pStates->Compile(); + + // get entry state + if (m_pStates->GetCount() && !IsConcurrent()) + for(int k = 0; k < m_pStates->GetCount() && !m_pEntry; k++) { + IfState* state = m_pStates->GetAt(k); + if (state->IsStart()) + m_pEntry = state->m_pEntry; + } + else + m_pEntry = this; + + if (m_pEntry == NULL && !IsConcurrent()) { + ok = 0; + Protest("undefined entry"); + } + + ok &= m_pOutTransitions->Compile(); + + SetFlag(CORRECT, ok); + + index = 1; + m_pOutTransitions->SetIndex(&index); + +} + +void IfState::SetParent(IfState* parent) { + m_pParent = parent; + for(int k = 0; k < m_pStates->GetCount(); k++) + m_pStates->GetAt(k)->SetParent(this); +} + +void IfState::SetIndex(int* Index) { + IfObject::SetIndex(Index); + m_pStates->SetIndex(Index); +} + +void IfState::Code(FILE* file) const { + // force unique state names here, but this method is const... + // char suffix[4]; + // sprintf(suffix, "%03d", m_iIndex); + // m_pName = (char*) realloc(m_pName, strlen(m_pName) + 4); + // strcat(m_pName, suffix); + + fprintf(file, "code(dispatch,%s,",m_pName); + if (IsStable() && !IsControl()) + fprintf(file, "%s", m_pParent->GetName()); + + for(int i = 0; i < m_pInputs->GetCount(); i++) { + IfSignal* signal = m_pInputs->GetAt(i); + fprintf(file, ",\n\t(%s", signal->GetName()); + for(int j = 0; j < m_pOutTransitions->GetCount(); j++) { + IfTransition* transition = m_pOutTransitions->GetAt(j); + IfAction* input = transition->GetInput(); + if (input && input->IsInput() && + ((IfInputAction*)input)->GetSignal() == signal) + fprintf(file, ",%d",transition->GetIndex()); + } + fprintf(file, ")"); + } + if (m_iInputNone) { + fprintf(file, ",\n\t("); + for(int j = 0; j < m_pOutTransitions->GetCount(); j++) { + IfTransition* transition = m_pOutTransitions->GetAt(j); + IfAction* input = transition->GetInput(); + if (!input || !input->IsInput()) + fprintf(file, ",%d", transition->GetIndex()); + } + fprintf(file, ")"); + } + fprintf(file, ")\n"); + + m_pOutTransitions->Code(file, "\n", "\n", "\n"); + m_pStates->Code(file, "\n", "\n", "\n"); +} + +void IfState::CodeEntry(FILE* file) const { + IfState* control = (IfState*) this; + while ( !control->IsControl() ) + control = control->GetParent(); + fprintf(file, "%s,%d,", control->GetName(), m_pEntry->GetIndex()); + if ( m_pEntry->IsConcurrent() ) + m_pEntry->CodeEntryRecursive(file); +} + +void IfState::CodeEntryRecursive(FILE* file) const { + // assert( IsConcurrent() ); + for(int k = 0; k < m_pStates->GetCount(); k++) { + IfState* state = m_pStates->GetAt(k); + // assert( state->IsControl() ); + fprintf(file, "%s,%d,", state->GetName(), state->GetEntry()->GetIndex()); + if (state->GetEntry()->IsConcurrent()) + state->GetEntry()->CodeEntryRecursive(file); + } +} + +void IfState::CodeExit(FILE* file) const { + IfState* control = (IfState*) this; + while ( !control->IsControl() ) + control = control->GetParent(); + control->CodeExitRecursive(file); +} + +void IfState::CodeExitRecursive(FILE* file) const { + if (IsControl()) + fprintf(file, "%s,-1,", GetName()); + for(int k = 0; k < m_pStates->GetCount(); k++) + m_pStates->GetAt(k)->CodeExitRecursive(file); +} + +unsigned IfState::GetStatus(const IfSignal* Signal) const { + // warning: INPUT, SAVE flags are synthetised from the top state! + unsigned status = 0; // INPUT = 1 | SAVE = 2 + for(IfState* state = (IfState*) this; state != NULL && + status != 3; state=state->m_pParent) { + if (state->m_pInputs->Find(Signal)) + status |= 1; + if (state->m_pSaves->Find(Signal)) + status |= 2; + } + return status; +} + +void IfState::CodeTable(FILE* file) const { + int i; + + IfList<IfSignal>* signals = + m_pProcess->GetSystem()->GetSignals(); + + fprintf(file, " {\"%s\", %d, %d, 0%s%s%s%s%s%s,\n", + m_pName, m_pParent ? m_pParent->m_iIndex : m_iIndex, + m_pEntry->m_iIndex, IsStable() ? "" : " | UNSTABLE", + GetFlag(TSIG) ? " | TSIG" : "", + GetFlag(TNONE) ? " | TNONE" : "", + m_iSuccess ? " | OSUCCESS" : "", + m_iError ? " | OERROR" : "", + GetFlag(CONTROL) ? " | CONTROL" : ""); + fprintf(file, " {"); + if(0 == signals->GetCount()) + fprintf(file, "(char)0"); + for(i = 0; i < signals->GetCount(); i++) { + IfSignal* signal = signals->GetAt(i); + if (i) fprintf(file, ","); + fprintf(file, "%d", GetStatus(signal)); + if ((i + 1) % 32 == 0) fprintf(file, "\n "); + } + fprintf(file, "},\n &if_%s_instance::_%s_dispatch},\n", + m_pProcess->GetName(), m_pName); + + for(i = 0; i < m_pStates->GetCount(); i++) + m_pStates->GetAt(i)->CodeTable(file); + +} + +int IfState::Use(const IfVariable* Variable) const { + int use = 0; + if (m_pTpc) + use |= m_pTpc->Use(Variable); + return use; +} + +int IfState::Def(const IfVariable* Variable) const { + return 0; +} + +IfState* IfState::LeastCommonAncestor(const IfState* s1, const IfState* s2) { + // assume max hierarchy depth 256, should be enough ... + IfState *p1[256], *p2[256], *s; + int n1, n2; + + for(n1 = 0, s = (IfState*) s1; s != NULL; s = s->GetParent()) + p1[n1++] = s; + for(n2 = 0, s = (IfState*) s2; s != NULL; s = s->GetParent()) + p2[n2++] = s; + + while (p1[n1-1] == p2[n2-1] && n1 >= 1 && n2 >= 1) { + s = p1[n1-1]; + n1--; n2--; + } + + return s; +} + diff --git a/src/model/state.h b/src/model/state.h new file mode 100644 index 0000000000000000000000000000000000000000..893060c3a71df19031c59dbf9484643c447fea85 --- /dev/null +++ b/src/model/state.h @@ -0,0 +1,128 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * state interface + * + */ + +class IfState : public IfObject { + public: + enum CFlag { STABLE = 1024, START = 2048, + TNONE = 4096, TSIG = 8192, + CONCURRENT = 16384, + SUCCESS = 32768, ERROR = 65536, // not used (Marius' observers) + CONTROL = 131072}; + + public: + IfState(IfConstraint* Tpc, + IfList<IfSignal>* Saves, + IfList<IfTransition>* Transitions, + IfList<IfState>* States, + char* Option[], + char* Name, + unsigned Flags = 0); + virtual ~IfState(); + + public: + inline IfConstraint* GetTpc() const { return m_pTpc; } + inline IfList<IfSignal>* GetSaves() const { return m_pSaves; } + inline IfList<IfTransition>* GetOutTransitions() const { return m_pOutTransitions; } + inline IfList<IfTransition>* GetTransitions() const { return GetOutTransitions(); } + inline IfList<IfState>* GetStates() const { return m_pStates; } + inline int IsStable() const { return GetFlag(STABLE) ? 1 : 0; } + inline int IsStart() const { return GetFlag(START) ? 1 : 0; } + inline int IsConcurrent() const { return GetFlag(CONCURRENT) ? 1 : 0; } + inline int IsControl() const { return GetFlag(CONTROL) ? 1 : 0; } + + inline IfList<IfTransition>* GetInTransitions() const { return m_pInTransitions; } + inline IfState* GetParent() const { return m_pParent; } + inline IfState* GetEntry() const { return m_pEntry; } + inline IfAutomatonEntity* GetProcess() const { return m_pProcess; } + + IfState* Find(const char*) const; + + + virtual const char* GetClass() const + { return "state"; } + virtual int IsState() const + { return 1; } + + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + virtual void SetParent(IfState* state); + virtual void SetIndex(int* Index); + + virtual void CodeEntry(FILE* file) const; + virtual void CodeEntryRecursive(FILE* file) const; + virtual void CodeExit(FILE* file) const; + virtual void CodeExitRecursive(FILE* file) const; + + public: + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + public: + virtual unsigned GetStatus(const IfSignal* Signal) const; + virtual void CodeTable(FILE* file) const; + + static IfState* + LeastCommonAncestor(const IfState*, const IfState*); + + protected: + IfConstraint* m_pTpc; // time progress condition + IfList<IfSignal>* m_pSaves; // saved signals + IfList<IfTransition>* m_pOutTransitions; // outgoing transitions + IfList<IfState>* m_pStates; // nested substates + int m_iSuccess; // success state marker + int m_iError; // error state marker + + protected: + IfAutomatonEntity* m_pProcess; // nesting process + IfList<IfTransition>* m_pInTransitions; // ingoing transitions + IfState* m_pParent; // parent state + IfState* m_pEntry; // entry state + IfList<IfSignal>* m_pInputs; // (local) input signals + int m_iInputNone; // (local) input none + +}; + diff --git a/src/model/statement.C b/src/model/statement.C new file mode 100644 index 0000000000000000000000000000000000000000..6e53ce018a068db4c43a0fc92c569bd8dc7249d1 --- /dev/null +++ b/src/model/statement.C @@ -0,0 +1,394 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of statements + * + */ + +#include "model.h" + +IfStatement::IfStatement(unsigned Flags) + : IfObject(NULL, Flags) { + m_pTransition = NULL; +} + +IfStatement::~IfStatement() { +} + +void IfStatement::PreCompile() { + IfObject::PreCompile(); +} + +void IfStatement::SetIndex(int* Index) { + // pure virtual +} + +void IfStatement::Alpha(FILE* file) const { + // pure virtual +} + +int IfStatement::Ask(const IfVariable* Variable) const { + // pure virtual + return 0; +} + +int IfStatement::Use(const IfVariable* Variable) const { + // pure virtual + return 0; +} + +int IfStatement::Def(const IfVariable* Variable) const { + // pure virtual + return 0; +} + +/* + * + * block statement implementation + * + */ + +IfBlockStatement::IfBlockStatement(IfList<IfBasicStatement>* Statements, + unsigned Flags) + : IfStatement(Flags) { + m_pStatements = Statements; +} + +IfBlockStatement::~IfBlockStatement() { + delete m_pStatements; +} + +void IfBlockStatement::Dump(FILE* file) const { + m_pStatements->Dump(file, "", "", ""); +} + +void IfBlockStatement::PreCompile() { + IfStatement::PreCompile(); + + int ok = m_pStatements->Compile(); + SetFlag(CORRECT, ok); +} + +void IfBlockStatement::SetIndex(int* Index) { + m_pStatements->SetIndex(Index); +} + +void IfBlockStatement::Alpha(FILE* file) const { + fprintf(file, "("); + for(int i = 0; i < m_pStatements->GetCount(); i++){ + m_pStatements->GetAt(i)->Alpha(file); + if (i < m_pStatements->GetCount() - 1) + fprintf(file, ","); + }; + fprintf(file, ")"); +} + +void IfBlockStatement::Code(FILE* file) const { + m_pStatements->Code(file, "", "\n", ""); +} + +int IfBlockStatement::Ask(const IfVariable* Variable) const { + int ask = 0; + for(int i = 0; i < m_pStatements->GetCount() && !ask; i++) + ask |= m_pStatements->GetAt(i)->Ask(Variable); + return ask; +} + +int IfBlockStatement::Use(const IfVariable* Variable) const { + int use = 0; + for(int i = 0; i < m_pStatements->GetCount() && !use; i++) { + use |= m_pStatements->GetAt(i)->Use(Variable); + if (m_pStatements->GetAt(i)->Def(Variable)) + break; + } + return use; +} + +int IfBlockStatement::Def(const IfVariable* Variable) const { + int def = 0; + for(int i = 0; i < m_pStatements->GetCount() && !def; i++) + def |= m_pStatements->GetAt(i)->Def(Variable); + return def; +} + +/* + * + * basic statement implementation + * + */ + +IfBasicStatement::IfBasicStatement(unsigned Flags) + : IfStatement(Flags) { +} + +IfBasicStatement::~IfBasicStatement() { +} + +void IfBasicStatement::PreCompile() { + IfStatement::PreCompile(); +} + +/* + * + * basic action statement implementation + * + */ + + +IfActionStatement::IfActionStatement(IfAction* Action, + unsigned Flags) + : IfBasicStatement(Flags) { + m_pAction = Action; +} + +IfActionStatement::~IfActionStatement() { + delete m_pAction; +} + +void IfActionStatement::Dump(FILE* file) const { + fprintf(file, "%s", indent(DEPTH)); + m_pAction->Dump(file); + fprintf(file, "\n"); +} + +void IfActionStatement::PreCompile() { + IfBasicStatement::PreCompile(); + + int ok = m_pAction->Compile(); + SetFlag(CORRECT, ok); +} + +void IfActionStatement::SetIndex(int* Index) { + m_pAction->SetIndex(Index); +} + +void IfActionStatement::Alpha(FILE* file) const { + fprintf(file, "("); + m_pAction->Alpha(file); + fprintf(file, ")"); +} + +void IfActionStatement::Code(FILE* file) const { + m_pAction->Code(file); +} + +int IfActionStatement::Ask(const IfVariable* Variable) const { + return m_pAction->Use(Variable) || m_pAction->Def(Variable); +} + +int IfActionStatement::Use(const IfVariable* Variable) const { + return m_pAction->Use(Variable); +} + +int IfActionStatement::Def(const IfVariable* Variable) const { + return m_pAction->Def(Variable); +} + +/* + * + * basic conditional statement implementation + * + */ + +IfConditionalStatement::IfConditionalStatement(IfExpression* Test, + IfBlockStatement* Then, + IfBlockStatement* Else, + unsigned Flags) + : IfBasicStatement(Flags) { + m_pTest = Test; + m_pThen = Then; + m_pElse = Else; +} + +IfConditionalStatement::~IfConditionalStatement() { + delete m_pTest; + delete m_pThen; + if (m_pElse) delete m_pElse; +} + +void IfConditionalStatement::Dump(FILE* file) const { + fprintf(file, "%sif ", indent(DEPTH)); + m_pTest->Dump(file); + fprintf(file, " then\n"); + DEPTH++; m_pThen->Dump(file); DEPTH--; + if (m_pElse) { + fprintf(file, "%selse\n", indent(DEPTH)); + DEPTH++; m_pElse->Dump(file); DEPTH--; + } + fprintf(file, "%sendif\n", indent(DEPTH)); +} + +void IfConditionalStatement::PreCompile() { + IfBasicStatement::PreCompile(); + + int ok = 1; + + ok &= m_pTest->Compile(); + ok &= m_pTest->Match(TYPES[IfBasicType::BOOLEAN]); + ok &= !m_pTest->IsTimed(); + + ok &= m_pThen->Compile(); + + if (m_pElse) + ok &= m_pElse->Compile(); + + SetFlag(CORRECT, ok); +} + +void IfConditionalStatement::SetIndex(int* Index) { + m_pThen->SetIndex(Index); + if (m_pElse) + m_pElse->SetIndex(Index); +} + +void IfConditionalStatement::Alpha(FILE* file) const { + fprintf(file, "(if,"); + m_pTest->Code(file); + fprintf(file, ","); + m_pThen->Alpha(file); + fprintf(file, ","); + if (m_pElse) + m_pElse->Alpha(file); + else + fprintf(file, "()"); + fprintf(file, ")"); +} + +void IfConditionalStatement::Code(FILE* file) const { + m_pThen->Code(file); + if (m_pElse) { + fprintf(file, "\n"); + m_pElse->Code(file); + } +} + +int IfConditionalStatement::Ask(const IfVariable* Variable) const { + int ask = 0; + ask |= m_pTest->Use(Variable); + ask |= m_pThen->Ask(Variable); + if (m_pElse) ask |= m_pElse->Ask(Variable); + return ask; +} + +int IfConditionalStatement::Use(const IfVariable* Variable) const { + int use = 0; + use |= m_pTest->Use(Variable); + use |= m_pThen->Use(Variable); + if (m_pElse) use |= m_pElse->Use(Variable); + return use; +} + +int IfConditionalStatement::Def(const IfVariable* Variable) const { + int def = 0; + if (m_pElse) + def |= m_pThen->Def(Variable) && m_pElse->Def(Variable); + return def; +} + +/* + * + * loop statement implementation + * + */ + +IfLoopStatement::IfLoopStatement(IfExpression* Test, + IfBlockStatement* Body, + unsigned Flags) + : IfBasicStatement(Flags) { + m_pTest = Test; + m_pBody = Body; +} + +IfLoopStatement::~IfLoopStatement() { + delete m_pTest; + delete m_pBody; +} + +void IfLoopStatement::Dump(FILE* file) const { + fprintf(file, "%swhile ", indent(DEPTH)); + m_pTest->Dump(file); + fprintf(file, " do\n"); + DEPTH++; m_pBody->Dump(file); DEPTH--; + fprintf(file, "%sendwhile\n", indent(DEPTH)); +} + +void IfLoopStatement::PreCompile() { + IfBasicStatement::PreCompile(); + + int ok = 1; + + ok &= m_pTest->Compile(); + ok &= m_pTest->Match(TYPES[IfBasicType::BOOLEAN]); + ok &= !m_pTest->IsTimed(); + + ok &= m_pBody->Compile(); + + SetFlag(CORRECT, ok); +} + +void IfLoopStatement::SetIndex(int* Index) { + m_pBody->SetIndex(Index); +} + +void IfLoopStatement::Alpha(FILE* file) const { + fprintf(file, "(while,"); + m_pTest->Code(file); + fprintf(file, ","); + m_pBody->Alpha(file); + fprintf(file, ")"); +} + +void IfLoopStatement::Code(FILE* file) const { + m_pBody->Code(file); +} + +int IfLoopStatement::Ask(const IfVariable* Variable) const { + return m_pTest->Use(Variable) || m_pBody->Ask(Variable); +} + +int IfLoopStatement::Use(const IfVariable* Variable) const { + return m_pTest->Use(Variable) || m_pBody->Use(Variable); +} + +int IfLoopStatement::Def(const IfVariable* Variable) const { + return 0; +} diff --git a/src/model/statement.h b/src/model/statement.h new file mode 100644 index 0000000000000000000000000000000000000000..8898d035fcf04f5bf62f0d82c95c657f35bc5890 --- /dev/null +++ b/src/model/statement.h @@ -0,0 +1,259 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract statement interface + * + */ + +class IfStatement : public IfObject { + + public: + IfStatement(unsigned Flags = 0); + virtual ~IfStatement(); + + public: + virtual const char* GetClass() const { return "statement"; } + virtual void PreCompile(); + virtual void SetIndex(int* Index); + virtual void Alpha(FILE* file) const; + + public: + virtual int Ask(const IfVariable* Variable) const; + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + public: + virtual int IsBlock() const { return 0; } + virtual int IsBasic() const { return 0; } + + protected: + IfTransition* m_pTransition; + +}; + +/* + * + * block statement interface + * + */ + +class IfBlockStatement : public IfStatement { + + public: + IfBlockStatement(IfList<IfBasicStatement>* Statements, + unsigned Flags = 0); + virtual ~IfBlockStatement(); + + public: + inline IfList<IfBasicStatement>* GetStatements() const + { return m_pStatements; } + + public: + virtual int IsBlock() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void SetIndex(int* Index); + virtual void Alpha(FILE* file) const; + virtual void Code(FILE* file) const; + + public: + virtual int Ask(const IfVariable* Variable) const; + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfList<IfBasicStatement>* m_pStatements; + +}; + +/* + * + * basic statement interface + * + */ + +class IfBasicStatement : public IfStatement { + + public: + IfBasicStatement(unsigned Flags = 0); + virtual ~IfBasicStatement(); + + public: + virtual int IsBasic() const { return 1; } + + virtual int IsAction() const { return 0; } + virtual int IsConditional() const { return 0; } + virtual int IsLoop() const { return 0; } + + virtual void PreCompile(); + +}; + +/* + * + * basic action statement interface + * + */ + +class IfActionStatement : public IfBasicStatement { + + public: + IfActionStatement(IfAction* Action, + unsigned Flags = 0); + virtual ~IfActionStatement(); + + public: + inline IfAction* GetAction() const + { return m_pAction; } + inline void SetAction(IfAction* Action) + { m_pAction = Action; } + + public: + virtual int IsAction() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void SetIndex(int* Index); + virtual void Alpha(FILE* file) const; + virtual void Code(FILE* file) const; + + public: + virtual int Ask(const IfVariable* Variable) const; + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfAction* m_pAction; + +}; + +/* + * + * basic conditional statement interface + * + */ + +class IfConditionalStatement : public IfBasicStatement { + + public: + IfConditionalStatement(IfExpression* Test, + IfBlockStatement* Then, + IfBlockStatement* Else, + unsigned Flags = 0); + virtual ~IfConditionalStatement(); + + public: + inline IfExpression* GetTest() const + { return m_pTest; } + inline IfBlockStatement* GetThen() const + { return m_pThen; } + inline IfBlockStatement* GetElse() const + { return m_pElse; } + + inline void SetTest(IfExpression* Test) + { m_pTest = Test; } + inline void SetThen(IfBlockStatement* Then) + { m_pThen = Then; } + inline void SetElse(IfBlockStatement* Else) + { m_pElse = Else; } + + public: + virtual int IsConditional() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void SetIndex(int* Index); + virtual void Alpha(FILE* file) const; + virtual void Code(FILE* file) const; + + public: + virtual int Ask(const IfVariable* Variable) const; + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pTest; + IfBlockStatement* m_pThen; + IfBlockStatement* m_pElse; + +}; + +/* + * + * basic loop statement interface + * + */ + +class IfLoopStatement : public IfBasicStatement { + + public: + IfLoopStatement(IfExpression* Test, + IfBlockStatement* Body, + unsigned Flags = 0); + virtual ~IfLoopStatement(); + + public: + inline IfExpression* GetTest() const + { return m_pTest; } + inline IfBlockStatement* GetBody() const + { return m_pBody; } + inline void SetTest(IfExpression* Test) + { m_pTest = Test; } + inline void SetBody(IfBlockStatement* Body) + { m_pBody = Body; } + + public: + virtual int IsLoop() const { return 1; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void SetIndex(int* Index); + virtual void Alpha(FILE* file) const; + virtual void Code(FILE* file) const; + + public: + virtual int Ask(const IfVariable* Variable) const; + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + IfExpression* m_pTest; + IfBlockStatement* m_pBody; + +}; diff --git a/src/model/transition.C b/src/model/transition.C new file mode 100644 index 0000000000000000000000000000000000000000..dff703fcbe7abd748cafa510b5069cac1262e487 --- /dev/null +++ b/src/model/transition.C @@ -0,0 +1,279 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of transitions + * + */ + +#include "model.h" + +const char* IfTransition::DEADLINE[] = { "eager", "delayable", "lazy" }; + +IfTransition::IfTransition(float Probability, + EDeadline Deadline, + int Priority, + IfAction* Acquire, + IfExpression* Provided, + IfConstraint* When, + IfAction* Input, + IfBlockStatement* Body, + IfAction* Terminator, + char* Name, + unsigned Flags) : + IfObject(Name, Flags) { + m_fProbability = Probability; + m_eDeadline = Deadline; + m_iPriority = Priority; + m_pAcquire = Acquire; + m_pProvided = Provided; + m_pWhen = When; + m_pInput = Input; + m_pBody = Body; + m_pTerminator = Terminator; + + m_pSource = NULL; + m_pProvidedTransformed = NULL; +} + +IfTransition::~IfTransition() { + if (m_pAcquire) delete m_pAcquire; + if (m_pProvidedTransformed) delete m_pProvidedTransformed; + if (m_pWhen) delete m_pWhen; + if (m_pInput) delete m_pInput; + delete m_pBody; + delete m_pTerminator; +} + +void IfTransition::Dump(FILE* file) const { + + if (GetProbability() != -1) + fprintf(file, "%sprobability %.6f;\n", indent(DEPTH), GetProbability()); + + if (!IsEager()) + fprintf(file, "%sdeadline %s;\n", indent(DEPTH), DEADLINE[m_eDeadline]); + if (m_iPriority != -1) + fprintf(file, "%spriority %d;\n;", indent(DEPTH), m_iPriority); + if (m_pAcquire) { + fprintf(file, " "); + m_pAcquire->Dump(file); + fprintf(file, "\n"); + } + if (m_pProvided) { + fprintf(file, "%sprovided ", indent(DEPTH)); + m_pProvided->Dump(file); + fprintf(file, ";\n"); + } + if (m_pWhen) { + fprintf(file, "%swhen ", indent(DEPTH)); + m_pWhen->Dump(file); + fprintf(file, ";\n"); + } + if (m_pInput) { + fprintf(file, "%s", indent(DEPTH)); + m_pInput->Dump(file); + fprintf(file, "\n"); + } + + DEPTH++; m_pBody->Dump(file); DEPTH--; + + fprintf(file, "%s", indent(DEPTH+1)); + m_pTerminator->Dump(file); +} + +void IfTransition::PreCompile() { + IfObject::PreCompile(); + + m_pSource = (IfState*) CONTEXT.Top(-1); + + int ok = 1, index = 0; + + if( m_pInput && m_pInput->IsMatch()) { + IfExpression* guard = ((IfMatchAction*)m_pInput)->GetObsGuard(); + if(guard) { + if(m_pProvided) m_pProvidedTransformed = new IfBinaryExpression(m_pProvided, IfBinaryExpression::AND, guard); + else m_pProvidedTransformed = guard; + } + } else + m_pProvidedTransformed = m_pProvided; + if (m_pAcquire) + ok &= m_pAcquire->Compile(); + if (m_pProvidedTransformed) { + ok &= m_pProvidedTransformed->Compile(); + ok &= m_pProvidedTransformed->Match(TYPES[IfBasicType::BOOLEAN]); + ok &= !m_pProvidedTransformed->IsTimed(); + } + if (m_pWhen) { + if (!m_pSource->IsStable()) + Protest("constraint in unstable state ignored"); + ok &= m_pWhen->Compile(); + SetFlag(TIMED, 1); + } + if (m_pInput) { + ok &= m_pInput->Compile(); + } + ok &= m_pBody->Compile(); + ok &= m_pTerminator->Compile(); + + if (m_pTerminator->IsNextstate()) { + IfNextstateAction* next = (IfNextstateAction*) m_pTerminator; + if (next->GetState()) + m_pTarget = next->GetState(); + else + m_pTarget = m_pSource; + } + else + m_pTarget = NULL; + + if (m_pTarget) + m_pTarget->GetInTransitions()->Add(this); + + if (m_pTarget != NULL && m_pSource != m_pTarget) { + IfState* lca = IfState::LeastCommonAncestor(m_pSource, m_pTarget); + // printf("lca(%s,%s) = %s\n", m_pSource->GetName(), m_pTarget->GetName(), lca->GetName()); + if (m_pTarget != lca) { + for(IfState* s = m_pTarget->GetParent(); ; s = s->GetParent()) { + if ( s->IsConcurrent() ) { + Protest("invalid transition on concurrent (sub)states"); ok = 0; + } + if (s == lca) break; + } + } + } + + SetFlag(CORRECT, ok); + + index = 0; + if (m_pAcquire) + m_pAcquire->SetIndex(&index); + if (m_pInput) + m_pInput->SetIndex(&index); + m_pBody->SetIndex(&index); + m_pTerminator->SetIndex(&index); + +} + +void IfTransition::Code(FILE* file) const { + IfAction::TRANSITION = (IfTransition*) this; + + fprintf(file, "code(fire,%s,%d,", + m_pSource->GetName(), m_iIndex); + + switch (m_eDeadline) { + case EAGER: fprintf(file, "EAGER,"); break; + case DELAYABLE: fprintf(file, "DELAYABLE,"); break; + case LAZY: fprintf(file, "LAZY,"); break; + } + if (m_pAcquire) + m_pAcquire->Alpha(file); + fprintf(file, ","); + + if (m_pProvidedTransformed) + m_pProvidedTransformed->Code(file); +// else if (m_pProvided) +// m_pProvided->Code(file); + fprintf(file, ","); + if (m_pSource->IsStable()) { + fprintf(file, "("); + if (m_pWhen) { + m_pWhen->Code(file); + fprintf(file, ","); + } + fprintf(file, "{0,0,0})"); + } + fprintf(file, ",\n\t"); + if (m_pInput) + m_pInput->Alpha(file); + fprintf(file, ","); + m_pBody->Alpha(file); + fprintf(file, ","); + m_pTerminator->Alpha(file); + fprintf(file, ","); + if( -1 != m_iPriority) fprintf(file, "%d", m_iPriority); + fprintf(file, ","); + if (GetProbability() != -1) fprintf(file, "%.6f", GetProbability()); + fprintf(file, ","); + fprintf(file, "%d", m_pProvided ? m_pProvided->GetLinenum() : + (m_pWhen ? m_pWhen->GetLinenum() : + (m_pInput ? m_pInput->GetLinenum() : + ( (m_pBody && m_pBody->GetStatements()->GetCount()) ? m_pBody->GetStatements()->GetAt(0)->GetLinenum() : + (m_pTerminator->GetLinenum()))))); + fprintf(file, ")\n"); + + if (m_pAcquire) { + m_pAcquire->Code(file); + fprintf(file, "\n"); + } + if (m_pInput) { + m_pInput->Code(file); + fprintf(file, "\n"); + } + m_pBody->Code(file); + fprintf(file, "\n"); + m_pTerminator->Code(file); + fprintf(file, "\n"); +} + +int IfTransition::Ask(const IfVariable* Variable) const { + int ask = 0; + if (m_pProvided) ask |= m_pProvided->Use(Variable); + if (m_pWhen) ask |= m_pWhen->Use(Variable); + if (m_pInput) ask |= m_pInput->Use(Variable) || m_pInput-Def(Variable); + if (m_pBody) ask |= m_pBody->Ask(Variable); + return ask; +} + +int IfTransition::Use(const IfVariable* Variable) const { + int use = 0; + if (m_pProvided) use |= m_pProvided->Use(Variable); + if (m_pWhen) use |= m_pWhen->Use(Variable); + if (m_pInput) use |= m_pInput->Use(Variable); + if (m_pBody && !m_pInput) use |= m_pBody->Use(Variable); + if (m_pBody && m_pInput) use |= m_pBody->Use(Variable) && !m_pInput->Def(Variable); + return use; +} + +int IfTransition::Def(const IfVariable* Variable) const { + int def = 0; + if (m_pInput) def |= m_pInput->Def(Variable); + if (m_pBody) def |= m_pBody->Def(Variable); + return def; +} diff --git a/src/model/transition.h b/src/model/transition.h new file mode 100644 index 0000000000000000000000000000000000000000..202d125a893a71bf3d761c5565eafa98b266ed64 --- /dev/null +++ b/src/model/transition.h @@ -0,0 +1,119 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * transition interface + * + */ + +class IfTransition : public IfObject { + + public: + enum EDeadline { EAGER = 0, DELAYABLE, LAZY }; + + public: + IfTransition(float Probability, + EDeadline Deadline, + int Priority, + IfAction* Acquire, + IfExpression* Provided, + IfConstraint* When, + IfAction* Input, + IfBlockStatement* Body, + IfAction* Terminator, + char* Name = NULL, + unsigned Flags = 0); + virtual ~IfTransition(); + + public: + inline float GetProbability() const { return m_fProbability; } + inline EDeadline GetDeadline() const { return m_eDeadline; } + inline int IsEager() const { return m_eDeadline == EAGER; } + inline int IsDelayable() const { return m_eDeadline == DELAYABLE; } + inline int IsLazy() const { return m_eDeadline == LAZY; } + inline int GetPriority() const { return m_iPriority; } + inline IfAction* GetAcquire() const { return m_pAcquire; } + inline IfExpression* GetProvided() const { return m_pProvided; } + inline IfConstraint* GetWhen() const { return m_pWhen; } + inline IfAction* GetInput() const { return m_pInput; } + inline IfBlockStatement* GetBody() const { return m_pBody; } + inline IfAction* GetTerminator() const { return m_pTerminator; } + inline IfState* GetSource() const { return m_pSource; } + inline IfState* GetTarget() const { return m_pTarget; } + + public: + inline void SetAcquire(IfAction* Acquire) { m_pAcquire = Acquire; } + inline void SetProvided(IfExpression* Provided) { m_pProvided = Provided; } + inline void SetWhen(IfConstraint* When) { m_pWhen = When; } + inline void SetInput(IfAction* Input) { m_pInput = Input; } + inline void SetBody(IfBlockStatement* Body) { m_pBody = Body; } + inline void SetTerminator(IfAction* Terminator) { m_pTerminator = Terminator; } + + public: + virtual const char* GetClass() const { return "transition"; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + virtual int Ask(const IfVariable* Variable) const; + virtual int Use(const IfVariable* Variable) const; + virtual int Def(const IfVariable* Variable) const; + + protected: + float m_fProbability; + EDeadline m_eDeadline; + int m_iPriority; + IfAction* m_pAcquire; + IfExpression* m_pProvided; + IfExpression* m_pProvidedTransformed; // allow transformation of guard in PreCompile, keeping old one also + IfConstraint* m_pWhen; + IfAction* m_pInput; + IfBlockStatement* m_pBody; + IfAction* m_pTerminator; + + IfState* m_pSource; + IfState* m_pTarget; + + protected: + static const char* DEADLINE[]; + +}; diff --git a/src/model/type.C b/src/model/type.C new file mode 100644 index 0000000000000000000000000000000000000000..43d55e59490f9acf93ee3e5718033a1becf215fb --- /dev/null +++ b/src/model/type.C @@ -0,0 +1,555 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of types + * + */ + +#include "model.h" + +IfType::IfType(char* Name, + unsigned Flags) + : IfObject(Name, Flags) { +} + +void IfType::PreCompile() { + IfObject::PreCompile(); + m_pContainer = (IfEntity*) CONTEXT.Top(-1); +} + +/* + * + * basic types + * + */ + +IfBasicType::IfBasicType(EKind Kind, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_eKind = Kind; +} + +/* + * + * enum types + * + */ + +IfEnumType::IfEnumType(IfList<IfEnumConstant>* Literals, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pLiterals = Literals; +} + +IfEnumType::~IfEnumType() { + delete m_pLiterals; +} + +void IfEnumType::Dump(FILE* file) const { + fprintf(file, "type %s = enum", m_pName); + m_pLiterals->DumpName(file, "\n ", ", ", "\n"); + fprintf(file, "endenum;"); +} + +void IfEnumType::PreCompile() { + IfType::PreCompile(); + + int ok = 1; + ok &= m_pLiterals->Compile(); + for(int i = 0; i < m_pLiterals->GetCount(); i++) + m_pLiterals->GetAt(i)->SetValue(i); + + SetFlag(CORRECT, ok); +} + +void IfEnumType::Code(FILE* file) const { + fprintf(file, "code(type,enum,%s,", m_pName); + m_pLiterals->DumpName(file, "",",",""); + fprintf(file, ")"); +} + +/* + * + * range type + * + */ + +IfRangeType::IfRangeType(IfConstant* Lower, + IfConstant* Upper, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pLower = Lower; + m_pUpper = Upper; +} + +IfRangeType::~IfRangeType() { + if (!m_pLower->GetName()) delete m_pLower; + if (!m_pUpper->GetName()) delete m_pUpper; +} + +void IfRangeType::Dump(FILE* file) const { + fprintf(file, "type %s = range ", m_pName); + m_pLower->DumpNameOrValue(file); + fprintf(file, " .. "); + m_pUpper->DumpNameOrValue(file); + fprintf(file, ";"); +} + +void IfRangeType::PreCompile() { + IfType::PreCompile(); + + int ok = 1; + + if (!m_pLower->GetName()) + ok &= m_pLower->Compile(); + if (!m_pUpper->GetName()) + ok &= m_pUpper->Compile(); + + ok &= m_pLower->GetType() == m_pUpper->GetType(); + + ok &= m_pLower->GetBase()->IsInteger() || + m_pLower->GetBase()->IsEnum(); + + SetFlag(CORRECT, ok); +} + +void IfRangeType::Code(FILE* file) const { + fprintf(file, "code(type,range,%s,%s,", + m_pName, m_pLower->GetType()->GetName()); + m_pLower->CodeNameOrValue(file); + fprintf(file, ","); + m_pUpper->CodeNameOrValue(file); + fprintf(file, ")"); +} + +int IfRangeType::GetSize() const { + int l = 0, u = 0; + if (m_pLower->GetBase()->IsInteger()) + l = ((IfIntegerConstant*) m_pLower->GetBase())->GetValue(); + if (m_pLower->GetBase()->IsEnum()) + l = ((IfEnumConstant*) m_pLower->GetBase())->GetValue(); + if (m_pUpper->GetBase()->IsInteger()) + u = ((IfIntegerConstant*) m_pUpper->GetBase())->GetValue(); + if (m_pUpper->GetBase()->IsEnum()) + u = ((IfEnumConstant*) m_pUpper->GetBase())->GetValue(); + return u-l; +} + +/* + * + * record type + * + */ + +IfRecordType::IfRecordType(IfList<IfVariable>* Fields, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pFields = Fields; +} + +IfRecordType::~IfRecordType() { + delete m_pFields; +} + +void IfRecordType::Dump(FILE* file) const { + if(GetFlag(PREDEFINED)) return; + fprintf(file, "type %s = record ", m_pName); + m_pFields->Dump(file, "\n ", ";\n ", ";\n"); + fprintf(file, "endrecord;"); +} + +void IfRecordType::PreCompile() { + IfType::PreCompile(); + + int ok = 1, tm = 0; + + ok &= m_pFields->Compile(); + for(int i = 0; i < m_pFields->GetCount(); i++) + tm |= m_pFields->GetAt(i)->GetType()->GetFlag(TIMED); + + SetFlag(CORRECT, ok); + SetFlag(TIMED, tm); +} + +void IfRecordType::Code(FILE* file) const { + fprintf(file, "code(type,record,%s,(", m_pName); + for(int i = 0; i < m_pFields->GetCount(); i++) { + IfVariable* field = m_pFields->GetAt(i); + fprintf(file, "%s,%s", field->GetName(), + field->GetType()->GetName()); + if (i < m_pFields->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "))"); +} + + +/* + * + * union type + * + */ + +IfUnionType::IfUnionType(IfList<IfVariable>* Fields, + char* Name, + unsigned bIsSigUnion, + unsigned Flags) + : IfType(Name, Flags) { + m_pFields = Fields; + m_bIsSigUnion = bIsSigUnion; +} + +IfUnionType::~IfUnionType() { + delete m_pFields; +} + +void IfUnionType::Dump(FILE* file) const { + // internal use only - for the moment + // no dump +} + +void IfUnionType::PreCompile() { + IfType::PreCompile(); + + int ok = 1, tm = 0; + + ok &= m_pFields->Compile(); + for(int i = 0; i < m_pFields->GetCount(); i++) + tm |= m_pFields->GetAt(i)->GetType()->GetFlag(TIMED); + + SetFlag(CORRECT, ok); + SetFlag(TIMED, tm); +} + +void IfUnionType::Code(FILE* file) const { + if(m_bIsSigUnion) fprintf(file, "code(type,sig_union,%s,(", m_pName); + else fprintf(file, "code(type,union,%s,(", m_pName); // incomplete macros !! + for(int i = 0; i < m_pFields->GetCount(); i++) { + IfVariable* field = m_pFields->GetAt(i); + fprintf(file, "%s,%s", field->GetName(), + field->GetType()->GetName()); + if (i < m_pFields->GetCount() - 1) + fprintf(file, ","); + } + fprintf(file, "))"); +} + + +/* + * + * array type + * + */ + +IfArrayType::IfArrayType(IfConstant* Length, + IfType* Element, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pLength = Length; + m_pElement = Element; +} + +IfArrayType::~IfArrayType() { + if (!m_pLength->GetName()) delete m_pLength; +} + +void IfArrayType::Dump(FILE* file) const { + fprintf(file, "type %s = array[", m_pName); + m_pLength->DumpNameOrValue(file); + fprintf(file, "] of %s;", m_pElement->GetName()); +} + +void IfArrayType::PreCompile() { + IfType::PreCompile(); + + int ok = 1, tm = 0; + + if (!m_pLength->GetName()) + ok &= m_pLength->Compile(); + + ok &= m_pLength->GetBase()->IsInteger(); + SetFlag(CORRECT, ok); + + tm = m_pElement->GetFlag(TIMED); + SetFlag(TIMED, tm); +} + +void IfArrayType::Code(FILE* file) const { + int l = ((IfIntegerConstant*) m_pLength->GetBase())->GetValue(); + + fprintf(file, "code(type,array,%s,%s,", + m_pName, m_pElement->GetName()); + m_pLength->CodeNameOrValue(file); + fprintf(file, ",%d)",l); +} + +/* + * + * string type + * + */ + +IfStringType::IfStringType(IfConstant* Length, + IfType* Element, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pLength = Length; + m_pElement = Element; +} + +IfStringType::~IfStringType() { + if (!m_pLength->GetName()) delete m_pLength; +} + +void IfStringType::Dump(FILE* file) const { + fprintf(file, "type %s = string[", m_pName); + m_pLength->DumpNameOrValue(file); + fprintf(file, "] of %s;", m_pElement->GetName()); +} + +void IfStringType::PreCompile() { + IfType::PreCompile(); + + int ok = 1, tm = 0; + + if (!m_pLength->GetName()) + ok &= m_pLength->Compile(); + + ok &= m_pLength->GetBase()->IsInteger(); + SetFlag(CORRECT, ok); + + tm = m_pElement->GetFlag(TIMED); + SetFlag(TIMED, tm); +} + +void IfStringType::Code(FILE* file) const { + fprintf(file, "code(type,string,%s,%s,", + m_pName, m_pElement->GetName()); + m_pLength->CodeNameOrValue(file); + fprintf(file, ")"); +} + +/* + * + * tree type + * + */ + +IfTreeType::IfTreeType(IfConstant* Width, + IfConstant* Height, + IfType* Element, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pWidth = Width; + m_pHeight = Height; + m_pElement = Element; +} + +IfTreeType::~IfTreeType() { + if (!m_pWidth->GetName()) delete m_pWidth; + if (!m_pHeight->GetName()) delete m_pHeight; +} + +void IfTreeType::Dump(FILE* file) const { + fprintf(file, "type %s = tree[", m_pName); + m_pWidth->DumpNameOrValue(file); + fprintf(file, ","); + m_pHeight->DumpNameOrValue(file); + fprintf(file, "] of %s;", m_pElement->GetName()); +} + +void IfTreeType::PreCompile() { + IfType::PreCompile(); + + int ok = 1, tm = 0; + + if (!m_pWidth->GetName()) + ok &= m_pWidth->Compile(); + if (!m_pHeight->GetName()) + ok &= m_pHeight->Compile(); + + ok &= m_pWidth->GetBase()->IsInteger(); + ok &= m_pHeight->GetBase()->IsInteger(); + SetFlag(CORRECT, ok); + + tm = m_pElement->GetFlag(TIMED); + SetFlag(TIMED, tm); +} + +void IfTreeType::Code(FILE* file) const { + fprintf(file, "code(type,tree,%s,%s,", + m_pName, m_pElement->GetName()); + m_pWidth->CodeNameOrValue(file); + fprintf(file, ","); + m_pHeight->CodeNameOrValue(file); + fprintf(file, ")"); +} + +/* + * + * abstract type + * + */ + +IfFunction::IfFunction(IfList<IfType>* Parameters, + IfType* Result, + char* Name, + unsigned Flags) : + IfObject(Name, Flags) { + m_pParameters = Parameters; + m_pResult = Result; +} + +IfFunction::~IfFunction() { + delete m_pParameters; +} + +void IfFunction::Link(IfType* Type) { + if (m_pResult == (IfType*)1) + m_pResult = Type; + for(int i = 0; i < m_pParameters->GetCount(); i++) + if (m_pParameters->GetAt(i) == (IfType*) 1) + m_pParameters->SetAt(i, Type); +} + +void IfFunction::Dump(FILE* file) const { + fprintf(file, "%s %s(", m_pResult->GetName(), m_pName); + m_pParameters->DumpName(file, "", ", ", ""); + fprintf(file, ");"); +} + +void IfFunction::PreCompile() { + IfObject::PreCompile(); + + int tm = 0; + for(int i = 0; i < m_pParameters->GetCount(); i++) + tm |= m_pParameters->GetAt(i)->GetFlag(TIMED); + tm |= m_pResult->GetFlag(TIMED); + if (tm) { + SetFlag(CORRECT, 0); + Protest("timed parameters"); + } +} + +void IfFunction::Code(FILE* file) const { + fprintf(file, "code(function, %s, (", m_pName); + for(int i = 0; i < m_pParameters->GetCount(); i++) { + IfType* type = m_pParameters->GetAt(i); + fprintf(file, "p%d,%s", i+1, type->GetName()); + if (i < m_pParameters->GetCount()-1) + fprintf(file, ","); + } + fprintf(file, "),%s)", m_pResult->GetName()); +} + + +IfAbstractType::IfAbstractType(IfList<IfFunction>* Functions, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pFunctions = Functions; +} + +IfAbstractType::~IfAbstractType() { + delete m_pFunctions; +} + +void IfAbstractType::Link() { + for(int i = 0; i < m_pFunctions->GetCount(); i++) + m_pFunctions->GetAt(i)->Link(this); +} + +void IfAbstractType::Dump(FILE* file) const { + fprintf(file, "type %s = abstract", m_pName); + m_pFunctions->Dump(file, "\n ", "\n ", "\n"); + fprintf(file, "endabstract;"); +} + +void IfAbstractType::PreCompile() { + IfType::PreCompile(); + + int ok = m_pFunctions->Compile(); + + SetFlag(CORRECT, ok); +} + +void IfAbstractType::Code(FILE* file) const { + fprintf(file, "code(type,abstract,%s)", m_pName); + m_pFunctions->Code(file, "\n", "\n", "\n"); +} + + +/* + * + * other type [rename] + * + */ + +IfOtherType::IfOtherType(IfType* Other, + char* Name, + unsigned Flags) + : IfType(Name, Flags) { + m_pOther = Other; +} + +IfOtherType::~IfOtherType() { +} + +void IfOtherType::Dump(FILE* file) const { + fprintf(file, "type %s = %s;", m_pName, m_pOther->GetName()); +} + +void IfOtherType::PreCompile() { + IfType::PreCompile(); +} + +void IfOtherType::Code(FILE* file) const { + fprintf(file, "code(type,other,%s,%s)", + m_pName, m_pOther->GetName()); +} diff --git a/src/model/type.h b/src/model/type.h new file mode 100644 index 0000000000000000000000000000000000000000..4200a4bdc36c08d9973785a6160a443b3d7899b7 --- /dev/null +++ b/src/model/type.h @@ -0,0 +1,439 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract type interface + * + */ + +class IfType : public IfObject { + public: + enum CFlag { PREDEFINED = 1024 }; + + public: + IfType(char* Name, + unsigned Flags = 0); + virtual ~IfType() {} + + public: + virtual const char* GetClass() const { return "type"; } + + virtual int IsBasic() const { return 0; } + virtual int IsEnum() const { return 0; } + virtual int IsRange() const { return 0; } + virtual int IsRecord() const { return 0; } + virtual int IsUnion() const { return 0; } + virtual int IsSigUnion() const { return 0; } + virtual int IsArray() const { return 0; } + virtual int IsString() const { return 0; } + virtual int IsTree() const { return 0; } + virtual int IsAbstract() const { return 0; } + virtual int IsOther() const { return 0; } + + virtual int IsScalar() const { return 0; } + + public: + virtual IfType* GetBase() const + { return (IfType*) this; } + int Match(const IfType* Type) const + { return GetBase() == Type->GetBase(); } + int Match(const IfType* Type1, const IfType* Type2) const + { return Match(Type1) || Match(Type2); } + int Match(const IfType* Type1, const IfType* Type2, const IfType* Type3) const + { return Match(Type1) || Match(Type2) || Match(Type3); } + + public: + virtual void PreCompile(); + + protected: + IfEntity* m_pContainer; + +}; + + +/* + * + * basic type interface + * + */ + +class IfBasicType : public IfType { + + public: + enum EKind {BOOLEAN = 0, INTEGER, REAL, CLOCK, PID, VOID}; + + public: + IfBasicType(EKind Kind, + char* Name, + unsigned Flags = 0); + virtual ~IfBasicType() {} + + public: + inline EKind GetKind() const { return m_eKind; } + + public: + virtual int IsBasic() const { return 1; } + virtual int IsScalar() const { return m_eKind != VOID; } + + protected: + EKind m_eKind; + +}; + +/* + * + * enum type interface + * + */ + +class IfEnumType : public IfType { + + public: + IfEnumType(IfList<IfEnumConstant>* Literals, + char* Name, + unsigned Flags = 0); + virtual ~IfEnumType(); + + public: + inline IfList<IfEnumConstant>* GetLiterals() const { return m_pLiterals; } + + public: + virtual int IsEnum() const { return 1; } + virtual int IsScalar() const { return 1; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfList<IfEnumConstant>* m_pLiterals; + +}; + +/* + * + * enum type interface + * + */ + +class IfRangeType : public IfType { + + public: + IfRangeType(IfConstant* Lower, + IfConstant* Upper, + char* Name, + unsigned Flags = 0); + virtual ~IfRangeType(); + + public: + inline IfConstant* GetLower() const { return m_pLower; } + inline IfConstant* GetUpper() const { return m_pUpper; } + int GetSize() const; + inline void SetLower(const IfConstant* Lower) + { m_pLower = (IfConstant*) Lower; } + inline void SetUpper(const IfConstant* Upper) + { m_pUpper = (IfConstant*) Upper; } + + public: + virtual int IsRange() const { return 1; } + virtual int IsScalar() const { return 1; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + public: + virtual IfType* GetBase() const + { return m_pLower->GetType(); } + + protected: + IfConstant* m_pLower; + IfConstant* m_pUpper; + +}; + +/* + * + * record type interface + * + */ + +class IfRecordType : public IfType { + + public: + IfRecordType(IfList<IfVariable>* Fields, + char* Name, + unsigned Flags = 0); + virtual ~IfRecordType(); + + public: + inline IfList<IfVariable>* GetFields() const { return m_pFields; } + + public: + virtual int IsRecord() const { return 1; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfList<IfVariable>* m_pFields; + +}; + +/* + * + * union type interface + * + */ + +class IfUnionType : public IfType { + + public: + IfUnionType(IfList<IfVariable>* Fields, + char* Name, + unsigned IsSigUnion, + unsigned Flags = 0); + virtual ~IfUnionType(); + + public: + inline IfList<IfVariable>* GetFields() const { return m_pFields; } + + public: + virtual int IsUnion() const { return 1; } + virtual int IsSigUnion() const { return m_bIsSigUnion; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfList<IfVariable>* m_pFields; + unsigned m_bIsSigUnion; + +}; + +/* + * + * array type interface + * + */ + +class IfArrayType : public IfType { + + public: + IfArrayType(IfConstant* Length, + IfType* Element, + char* Name, + unsigned Flags = 0); + virtual ~IfArrayType(); + + public: + inline IfConstant* GetLength() const { return m_pLength; } + inline IfType* GetElement() const { return m_pElement; } + inline void SetLength(const IfConstant* Length) + { m_pLength = (IfConstant*) Length; } + + public: + virtual int IsArray() const { return 1; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfConstant* m_pLength; + IfType* m_pElement; + +}; + +/* + * + * string type interface + * + */ + +class IfStringType : public IfType { + + public: + IfStringType(IfConstant* Length, + IfType* Element, + char* Name, + unsigned Flags = 0); + virtual ~IfStringType(); + + public: + inline IfConstant* GetLength() const { return m_pLength; } + inline IfType* GetElement() const { return m_pElement; } + + public: + virtual int IsString() const { return 1; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfConstant* m_pLength; + IfType* m_pElement; + +}; + +/* + * + * tree type interface + * + */ + +class IfTreeType : public IfType { + + public: + IfTreeType(IfConstant* Width, + IfConstant* Height, + IfType* Element, + char* Name, + unsigned Flags = 0); + virtual ~IfTreeType(); + + public: + inline IfConstant* GetWidth() const { return m_pWidth; } + inline IfConstant* GetHeight() const { return m_pHeight; } + inline IfType* GetElement() const { return m_pElement; } + + public: + virtual int IsTree() const { return 1; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfConstant* m_pWidth; + IfConstant* m_pHeight; + IfType* m_pElement; + +}; + +/* + * + * abstract type interface + * + */ + +class IfFunction : public IfObject { + + public: + IfFunction(IfList<IfType>* Parameters, + IfType* Results, + char* Name, + unsigned Flags = 0); + virtual ~IfFunction(); + + public: + virtual void Link(IfType* Type); + + public: + inline IfList<IfType>* GetParameters() const { return m_pParameters; } + inline IfType* GetResult() const { return m_pResult; } + + public: + virtual const char* GetClass() const { return "function"; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfList<IfType>* m_pParameters; + IfType* m_pResult; + +}; + + +class IfAbstractType : public IfType { + + public: + IfAbstractType(IfList<IfFunction>* Functions, + char* Name, + unsigned Flags = 0); + virtual ~IfAbstractType(); + + public: + inline IfList<IfFunction>* GetFunctions() const { return m_pFunctions; } + + public: + virtual void Link(); + + public: + virtual int IsAbstract() const { return 1; } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + protected: + IfList<IfFunction>* m_pFunctions; + +}; + +/* + * + * other type interface [rename] + * + */ + +class IfOtherType : public IfType { + + public: + IfOtherType(IfType* Type, + char* Name, + unsigned Flags = 0); + virtual ~IfOtherType(); + + public: + inline IfType* GetOther() const { return m_pOther; } + + public: + virtual int IsOther() const { return 1; } + virtual int IsScalar() const { return m_pOther->IsScalar(); } + virtual void Dump(FILE*) const; + virtual void PreCompile(); + virtual void Code(FILE*) const; + + public: + virtual IfType* GetBase() const + { return m_pOther->GetBase(); } + + protected: + IfType* m_pOther; + +}; diff --git a/src/model/variable.C b/src/model/variable.C new file mode 100644 index 0000000000000000000000000000000000000000..699359c1c783fdf0e1e9197d5df87de0446355fb --- /dev/null +++ b/src/model/variable.C @@ -0,0 +1,119 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * implementation of variables + * + */ + +#include "model.h" + +const char* IfVariable::MODE[] = {"in", "inout", "out", ""}; + +const char* IfVariable::SCOPE[] = {"public", "private", ""}; + +IfVariable::IfVariable(EKind Kind, + EScope Scope, + EMode Mode, + IfType* Type, + IfExpression* Initializer, + char* Name, + unsigned Flags) : + IfObject(Name, Flags) { + m_eKind = Kind; + m_eScope = Scope; + m_eMode = Mode; + m_pType = Type; + m_pInitializer = Initializer; +} + +IfVariable::~IfVariable() { + if (m_pInitializer) delete m_pInitializer; +} + +void IfVariable::Dump(FILE* file) const { + switch (m_eKind) { + case VAR: + fprintf(file, "var %s %s", + m_pName, m_pType->GetName()); + if (m_pInitializer) { + fprintf(file, " := "); + m_pInitializer->Dump(file); + } + fprintf(file, " %s;", + SCOPE[m_eScope]); break; + case FPAR: + fprintf(file, "%s %s %s", + MODE[m_eMode], m_pName, m_pType->GetName()); break; + case FIELD: + fprintf(file, "%s %s", + m_pName, m_pType->GetName()); break; + case EXISTS: + fprintf(file, "exists %s %s", + m_pName, m_pType->GetName()); break; + case FORALL: + fprintf(file, "forall %s %s", + m_pName, m_pType->GetName()); break; + } +} + +void IfVariable::PreCompile() { + IfObject::PreCompile(); + + if (m_pInitializer) { + int ok = 1; + ok &= m_pInitializer->Compile(); + ok &= m_pInitializer->Match(m_pType); + ok &= !m_pInitializer->IsTimed(); + SetFlag(CORRECT, ok); + + if (!m_pInitializer->IsConstant()) + Protest("non-constant initializer"); + } + + SetFlag(TIMED, m_pType->GetFlag(TIMED)); +} + +void IfVariable::Code(FILE* file) const { + if (IsVar()) fprintf(file, "m_var."); + if (IsFpar()) fprintf(file, "m_par."); + fprintf(file, "%s", m_pName); +} diff --git a/src/model/variable.h b/src/model/variable.h new file mode 100644 index 0000000000000000000000000000000000000000..9cb9014858e0f9ac44187fbfea23d9c9de231fb1 --- /dev/null +++ b/src/model/variable.h @@ -0,0 +1,107 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * variable interface + * + */ + +class IfVariable : public IfObject { + + public: + enum EKind + { VAR, FPAR, FIELD, EXISTS, FORALL }; + enum EScope + { PUBLIC, PRIVATE, NOSCOPE}; + enum EMode + { IN, INOUT, OUT, NOMODE}; + enum CFlag + { IMPORTED = 1024 }; + + public: + IfVariable(EKind Kind, + EScope Scope, + EMode Mode, + IfType* Type, + IfExpression* Initializer, + char* Name, + unsigned Flags = 0); + virtual ~IfVariable(); + + public: + inline EKind GetKind() const { return m_eKind; } + inline int IsVar() const { return m_eKind == VAR; } + inline int IsFpar() const { return m_eKind == FPAR; } + inline int IsField() const { return m_eKind == FIELD; } + inline int IsExists() const { return m_eKind == EXISTS; } + inline int IsForall() const { return m_eKind == FORALL; } + + inline EScope GetScope() const { return m_eScope; } + inline int IsPrivate() const { return m_eScope == PRIVATE; } + inline int IsPublic() const { return m_eScope == PUBLIC; } + inline void SetScope(EScope Scope) { m_eScope = Scope; } + + inline EMode GetMode() const { return m_eMode; } + inline int IsIn() const { return m_eMode == IN; } + inline int IsInout() const { return m_eMode == INOUT; } + inline int IsOut() const { return m_eMode == OUT; } + + inline IfType* GetType() const { return m_pType; } + inline IfExpression* GetInitializer() const { return m_pInitializer; } + + public: + virtual const char* GetClass() const { return "variable"; } + virtual void Dump(FILE* file) const; + virtual void PreCompile(); + virtual void Code(FILE* file) const; + + public: + static const char* MODE[]; + static const char* SCOPE[]; + + protected: + EKind m_eKind; + EMode m_eMode; + EScope m_eScope; + IfExpression* m_pInitializer; + IfType* m_pType; + +}; diff --git a/src/simulator-t/Makefile b/src/simulator-t/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..67c8bbf244a31d7d7d9a8b63187e0aa59fa3f9b7 --- /dev/null +++ b/src/simulator-t/Makefile @@ -0,0 +1,70 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +.SUFFIXES: +.SUFFIXES: .C .i .o + + SRC = explorator.C filter.c xmlexplorator.C + + OBJ = $(OBJDIR)/explorator.o \ + $(OBJDIR)/filter.o \ + $(OBJDIR)/xmlexplorator.o + + LIB = libexplorator.a + +############################# + +build: $(LIB) + + +install: build + -mv -f $(LIB) $(IF)/bin + +clean: + -rm -f $(OBJ) $(LIB) + +############################# + +$(LIB): $(OBJ) + $(AR) cql $@ $(OBJ) + +$(OBJDIR)/%.o: %.C + $(CC) $(CFLAGS) -o $(OBJDIR)/$*.o -I$(IF)/src/simulator $*.C + diff --git a/src/simulator-t/explorator.C b/src/simulator-t/explorator.C new file mode 100644 index 0000000000000000000000000000000000000000..962f453887466216ee03dcf510f25d2929001b68 --- /dev/null +++ b/src/simulator-t/explorator.C @@ -0,0 +1,1346 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#ifdef win32native +#define _WIN32_WINNT 0x0500 +#include <windows.h> +#include <winbase.h> +#include <io.h> +#else +#include <unistd.h> +#endif + +#include <fstream> +#include <signal.h> +#include <time.h> + +#include "simulator.h" + +#include "explorator.h" +#include "xmlexplorator.h" +#include "filter.h" + +// global options +int opt_qxml = 0; +int opt_txml = 0; + +/* + * + * explorator : implements abstract graph exploration + * + */ + +IfExplorator* IfExplorator::XP = NULL; + +#ifdef win32native +HANDLE IfExplorator::m_hTimerThread = NULL; + +DWORD WINAPI TimerCycle(LPVOID lpParameter) +{ + while(1) { + SleepEx(1000, 0); + if (IfExplorator::XP) IfExplorator::XP->alarm(); + } +} + +#else +inline void IfExplorator::cb_alarm(int) { + if (IfExplorator::XP) IfExplorator::XP->alarm(); +} +#endif + +void PrismPrintHeader(FILE* file) +{ + fprintf(file, "nondeterministic\n\n"); + fprintf(file, "const STATE_MAX = ?; \n\n"); + + fprintf(file, "module IfSystem\n\n"); + fprintf(file, "s : [0..STATE_MAX];\n"); + fprintf(file, "succ : bool;\n"); + fprintf(file, "err : bool;\n\n"); +} + +void PrismRePrintHeader(FILE* file, int q_count) +{ + fprintf(file, "nondeterministic\n\n"); + fprintf(file, "const STATE_MAX = %d;", q_count); +} + +void PrismPrintTransition(FILE* file, int source, int target, int succ, int err, double proba = 1) +{ + static double sum = 1; + + if( proba == 0 ) return; + + if(sum == 1) { + if(proba == 1) + fprintf(file, "\t[] (s=%d) -> (s'=%d) & (succ'=%s) & (err'=%s);\n", + source, target, succ?"true":"false", err?"true":"false"); + else { + fprintf(file, "\t[] (s=%d) -> %.6f:(s'=%d) & (succ'=%s) & (err'=%s)", + source, proba, target, succ?"true":"false", err?"true":"false"); + sum = proba; + } + } else { + if(sum+proba>=1) proba = 1-sum; + fprintf(file, " + %.6f:(s'=%d) & (succ'=%s) & (err'=%s)", + proba, target, succ?"true":"false", err?"true":"false"); + sum += proba; + + if( sum >= 1-1E-16 ) { + sum = 1; + fprintf(file,";\n"); + } + } +} + +void PrismPrintEnd(FILE* file) +{ + fprintf(file, "endmodule\n\n"); +} + +IfExplorator::IfExplorator(const IfEngine* engine, + const char* q_filename, + const char* t_filename, + const char* prism_filename, + const unsigned flags, + const unsigned long evFilter) + : IfDriver(engine) { + + q_file = q_filename ? fopen(q_filename, "w") : NULL; + t_file = t_filename ? fopen(t_filename, "w") : NULL; + prism_file = prism_filename ? fopen(prism_filename, "w") : NULL; + if (t_file && !opt_txml) fprintf(t_file, "des(0,?,?) \n"); + if (t_file && opt_txml) fprintf(t_file,"<IfGraph states = \"?\" transitions = \"?\"> \n"); + + if (prism_file) { + ::PrismPrintHeader(prism_file); + } + + q_count = 0; + t_count = 0; + m_flags = flags; + m_evFilter = evFilter; + + XP = this; + +#ifdef win32native + + if(m_hTimerThread == NULL) + m_hTimerThread = CreateThread(NULL,0xF000,TimerCycle, NULL, 0, NULL); + +#else + + signal(SIGALRM, cb_alarm); + +#endif + + m_time = 0; +} + +IfExplorator::~IfExplorator() { + XP = NULL; + + if (q_file) + fclose(q_file); + + if (t_file && !opt_txml) { + rewind(t_file); + fprintf(t_file,"des(0,%d,%d)", t_count, q_count); + fclose(t_file); + } + if (t_file && opt_txml) { + fprintf(t_file,"</IfGraph>"); + rewind(t_file); + fprintf(t_file,"<IfGraph states = \"%d\" transitions = \"%d\">", q_count, t_count); + fclose(t_file); + } + if (prism_file) { + ::PrismPrintEnd(prism_file); + rewind(prism_file); + ::PrismRePrintHeader(prism_file, q_count); + fclose(prism_file); + } + + status(); fprintf(stderr, "\n"); +} + +void IfExplorator::run() { + // abstract +} + +void IfExplorator::visit(const IfConfig* source, const IfLabel* label, + const IfConfig* target) { + if (t_file && !opt_txml) { + fprintf(t_file, "(%d,\"", source->getMark() & INDEXMASK); + if (m_flags & SP) { + for(int i = 0; i < label->getLength(); i++) { + if( !(m_evFilter & 1<<label->getAt(i)->getKind()) ) { + label->getAt(i)->print(t_file); + if (i < label->getLength() - 1) { + fprintf(t_file, "\",%d)\n(%d,\"", q_count, q_count); + q_count++; t_count++; + } + } + } + } + else { + IfLabel::setEvPrintFilter(m_evFilter); + label->print(t_file); + IfLabel::setEvPrintFilter(0); + } + if ( (m_flags & MS) && target->isObsSuccess() ) + fprintf(t_file, "&success "); + if ( (m_flags & ME) && target->isObsError() ) + fprintf(t_file, "&error "); + fprintf(t_file, "\",%d)\n", target->getMark() & INDEXMASK); + } + if (t_file && opt_txml) { + fprintf(t_file, "<IfTransition source=\"%d\" target=\"%d\" %s %s >", + source->getMark() & INDEXMASK, + target->getMark() & INDEXMASK, + ((m_flags & MS) && target->isObsSuccess())?"success = \"true\"":"", + ((m_flags & ME) && target->isObsError())?"error = \"true\"":"" ); + if (m_flags & SP) { + //!!!TODO + } + else { + // output xml + std::stringstream s; + label->printXML(s); s << '\0'; + fputs(s.str().c_str(), t_file); + } + fprintf(t_file, "</IfTransition>"); + } + if (prism_file) { + double proba = 1; + for(int i = 0; i < label->getLength(); i++) { + if(label->getAt(i)->getKind() == IfEvent::PROBABILITY) + proba = label->getAt(i)->getAuxProbability(); + } + ::PrismPrintTransition(prism_file, source->getMark() & INDEXMASK, target->getMark() & INDEXMASK, target->isObsSuccess(), target->isObsError(), proba); + } +} + +void IfExplorator::visit(const IfConfig* source) { + if (q_file) { + if(!opt_qxml) { + fprintf(q_file, "\n%d:\n", source->getMark() & INDEXMASK); + source->print(q_file); + } else { + // output xml + std::stringstream s; + fprintf(q_file, "\n<state index=\"%d\">\n", source->getMark() & INDEXMASK); + source->printXML(s); s << '\0'; + fputs(s.str().c_str(), q_file); + fprintf(q_file, "\n</state>\n"); + } + } + if ( (m_flags & MS) && source->isObsSuccess() ) { + fprintf(stderr, "reached success state [%d]\n", source->getMark() & INDEXMASK); + } + if ( (m_flags & ME) && source->isObsError() ) { + fprintf(stderr, "reached error state [%d]\n", source->getMark() & INDEXMASK); + } +} + +void IfExplorator::status() const { +#ifndef win32native + fprintf(stderr, "%c%02d:%02d:%02d %9d/s %9d/t ", + 13, m_time / 3600, m_time % 3600 / 60, m_time % 60, + q_count, t_count); +#else + char s[256]; + sprintf(s, "%c%02d:%02d:%02d %9d/s %9d/t ", + 13, m_time / 3600, m_time % 3600 / 60, m_time % 60, + q_count, t_count); + _write(1,s, strlen(s)); +#endif +} + +void IfExplorator::alarm() { +#ifndef win32native + signal(SIGALRM, cb_alarm); ::alarm(1); +#endif + m_time++; + status(); +} + +/* + * + * bfs explorator : implements breadth-first search exploration + * + */ + +IfBfsExplorator::IfBfsExplorator(const IfEngine* engine, + const char* q_filename, + const char* t_filename, + const char* prism_filename, + const unsigned flags, + const unsigned long evFilter) + : IfExplorator(engine, q_filename, t_filename, prism_filename, flags, evFilter) { + + bfs.size = 8; + bfs.queue = (IfConfig**) malloc(bfs.size * sizeof(IfConfig*)); + bfs.head = bfs.tail = 0; + +#ifndef win32native + ::alarm(1); +#endif +} + +IfBfsExplorator::~IfBfsExplorator() { + free(bfs.queue); +} + +void IfBfsExplorator::explore(IfConfig* source, IfLabel* label, + IfConfig* target) { + if (! (target->getMark() & REACHED)) { + target->setMark((q_count++) | REACHED); + + bfs.queue[bfs.tail] = target; + ++bfs.tail %= bfs.size; + + if (bfs.head == bfs.tail) { + bfs.queue = + (IfConfig**) realloc(bfs.queue, + 2 * bfs.size * sizeof(IfConfig*)); + memmove(bfs.queue + bfs.size, + bfs.queue, + bfs.tail * sizeof(IfConfig*)); + bfs.tail += bfs.size; + bfs.size += bfs.size; + } + } + + visit(source, label, target); + + t_count++; +} + +void IfBfsExplorator::run() { + run(NULL); +} + +void IfBfsExplorator::run(IfConfig* start) { + IfConfig* s = start ? start : m_engine->start(); + + s->setMark((q_count++) | REACHED); + + bfs.queue[bfs.tail++] = s; + + while (bfs.head != bfs.tail) { + s = bfs.queue[bfs.head]; + ++bfs.head %= bfs.size; + + m_engine->run(s); + + visit(s); + } +} + +/* + * + * dfs explorator : implements depth-first search exploration + * + */ + +IfDfsExplorator::IfDfsExplorator(const IfEngine* engine, + const char* q_filename, + const char* t_filename, + const char* prism_filename, + const unsigned flags, + const unsigned ind_flags, + const unsigned long evFilter) + : IfExplorator(engine, q_filename, t_filename, prism_filename, flags, evFilter) { + + dfs.stack = NULL; + dfs.depth = 0; + m_ind_flags = ind_flags; + +#ifndef win32native + ::alarm(1); +#endif +} + +IfDfsExplorator::~IfDfsExplorator() { +} + +void IfDfsExplorator::explore(IfConfig* source, IfLabel* label, + IfConfig* target){ + Successor* su = new Successor; + //su->state = target->deepStore(); - if store is not done by Engine + su->state = target; + su->label = label->copy(); + su->next = dfs.stack->pending; + dfs.stack->pending = su; +} + +void IfDfsExplorator::run() { + run(NULL); +} + +int FIND_BRANCH_MIN=2; + +void IfDfsExplorator::run(IfConfig* start) { + Successor* su = NULL; + Stack* st = NULL, *tt = NULL; + + tt = new Stack; + tt->tail = NULL; + tt->pending = NULL; + tt->label = NULL; + tt->state = start ? start : m_engine->start(); + tt->state->setMark((q_count++) | REACHED | STACKED); + + dfs.depth++; + dfs.stack = tt; + m_engine->run(tt->state); + if (m_flags & PO) restrict(); + + visit(tt->state); + + while (dfs.stack) { + st = dfs.stack; + su = st->pending; + + if (su != NULL) { + + if (! (su->state->getMark() & REACHED)) { + tt = new Stack; + tt->tail = st; + tt->pending = NULL; + tt->state = su->state; + tt->label = su->label; + tt->state->setMark((q_count++) | REACHED | STACKED); + + dfs.depth++; + dfs.stack = tt; +try { + m_engine->run(tt->state); +} catch(IfDynamicError d) { + // catch Instance Addressing Faults + std::ofstream file("dump.scn"); + file << "<scenario>"; + printStackScn(file); + file << "</scenario>"; + file.close(); + exit(1); +} + if (m_flags & PO) restrict(); + + if (m_flags & FB) { + int bCnt = 0; + for(Successor* fbs = dfs.stack->pending; fbs != NULL; fbs = fbs->next) bCnt++; + if(bCnt >= FIND_BRANCH_MIN) { + cout << "-- More than " << FIND_BRANCH_MIN << " dependent branches found in state. Scenario saved in fb.scn.\n"; + cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"; + for(Successor* fbs = dfs.stack->pending; fbs != NULL; fbs = fbs->next) { + cout << "-----------------------\n"; + fbs->label->printXML(cout); + } + cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"; + std::ofstream file("fb.scn"); + file << "<scenario>"; + printStackScn(file); + file << "</scenario>"; + file.close(); + m_flags &= ~FB; + } + } + + visit(tt->state); + } + + visit(st->state, su->label, su->state); + + st->pending = su->next; + //delete su->label; + delete su; + + t_count++; + } + + else { + unsigned mark = st->state->getMark(); + + st->state->setMark(mark & (~STACKED)); + if(st->label) delete st->label; + dfs.stack = dfs.stack->tail; + delete st; + + dfs.depth--; + } + } + +} + +#define EVSETMAXSIZE 16384 + +void IfDfsExplorator::restrict() { + Successor *su = NULL, *si = NULL, *st = NULL; + + // cycles / time progress detection... + for(su = dfs.stack->pending; su != NULL; su = su->next) { + if (su->state->getMark() & STACKED) + break; + if (su->label->getAt(0)->getKind() == IfEvent::TICK) + break; + } + if (su != NULL) + return; + + // build the whole event set + static IfString<IfObject> ls(EVSETMAXSIZE); // contains all IfLabel's + unsigned i = 0; + for(su = dfs.stack->pending; su != NULL; su = su->next) + ls.setAt(i++,su->label); + ls.setAt(i,NULL); + + // search one independent process... + for(si = dfs.stack->pending; si != NULL; si = su) { + int ok = 1; + for (su = si; + su != NULL && su->label->getPid() == si->label->getPid(); + su = su->next) + ok &= su->label->isIndependent(m_ind_flags); + if (ok) + break; + } + if (si == NULL) + return; + + // keep one independent process... + su = dfs.stack->pending; + dfs.stack->pending = NULL; + for (; su != NULL; su = st) { + st = su->next; + if (su->label->getPid() == si->label->getPid()) { + su->next = dfs.stack->pending; + dfs.stack->pending = su; + } + else { + delete su->label; + delete su; + } + } +} + +void IfDfsExplorator::status() const { + IfExplorator::status(); +#ifndef win32native + fprintf(stderr, " %4d/d ", dfs.depth); +#else + char s[256]; + sprintf(s, " %4d/d ", dfs.depth); + _write(1,s, strlen(s)); +#endif +} + +void IfDfsExplorator::visit(const IfConfig* source) { + IfExplorator::visit(source); + + if (((m_flags & MS) && source->isObsSuccess()) || + ((m_flags & ME) && source->isObsError())) { + static int errorScnCnt = 1; + static int successScnCnt = 1; + char fileName[64]; + if ( source->isObsSuccess() ) sprintf(fileName, "s%d.scn", successScnCnt++); + if ( source->isObsError() ) sprintf(fileName, "e%d.scn", errorScnCnt++); + + std::ofstream file(fileName); + file << "<scenario>"; + printStackScn(file); + file << "</scenario>"; + file.close(); + } +} + +void IfDfsExplorator::printStackScn(std::ostream &out, Stack* left) { + if(left == NULL) left = dfs.stack; + if(left == NULL) return; + if(left->tail && left->tail->label) + printStackScn(out, left->tail); + if(left->label) { + left->label->printXML(out); + } +} + +/* + * + * random explorator : implements random exploration + * + */ + +IfRandomExplorator::IfRandomExplorator(const IfEngine* engine, + const char* q_filename, + const char* t_filename, + const char* prism_filename, + const unsigned flags, + const unsigned long evFilter) + : IfExplorator(engine, q_filename, t_filename, prism_filename, flags, evFilter) { + + random.source = NULL; + random.label = NULL; + random.target = NULL; + + random.count = 0; + + srand(time(NULL)); +} + +IfRandomExplorator::~IfRandomExplorator() { +} + +void IfRandomExplorator::explore(IfConfig* source, IfLabel* label, + IfConfig* target) { + if (rand() % ++random.count == 0) { + random.target = target; + random.label = new IfLabel(*label); + } + + t_count++; +} + +void IfRandomExplorator::run() { + random.source = m_engine->start(); + + while (random.source) { +#ifndef win32native + char clear[] = {27,91,72,27,91,50,74,0}; + printf("%s", clear); +#endif + if( random.label ) { + printf("\nfire : "); + IfLabel::setEvPrintFilter(m_evFilter); + random.label->print(stdout); + IfLabel::setEvPrintFilter(0); + delete random.label; + } + + printf("\nstatus: %d steps\n\n", q_count); + random.source->print(stdout); + + q_count++; + + random.target = NULL; random.count = 0; + m_engine->run(random.source); + + random.source = random.target; + +#ifdef win32native + Sleep(500); // one second nap +#else + usleep(500000); +#endif + } + +} + +void IfRandomExplorator::status() const { +} + +/* + * + * interactive explorator + * + */ + +IfInteractiveExplorator::IfInteractiveExplorator(const IfEngine* engine, + const char* q_filename, + const char* t_filename, + const char* prism_filename, + const unsigned flags, + const unsigned long evFilter) + : IfExplorator(engine, q_filename, t_filename, prism_filename, flags, evFilter) , m_path() { + + m_source = NULL; + m_nMaxSuccessors = 64; + m_labels = (IfLabel**)malloc(m_nMaxSuccessors*sizeof(IfLabel*)); + m_targets = (IfConfig**)malloc(m_nMaxSuccessors*sizeof(IfLabel*)); + m_nCurrentSuccessor = 0; +} + +IfInteractiveExplorator::~IfInteractiveExplorator() { + free(m_labels); + free(m_targets); +} + +void IfInteractiveExplorator::explore(IfConfig* source, IfLabel* label, + IfConfig* target) { + if(m_nCurrentSuccessor == m_nMaxSuccessors) { + m_nMaxSuccessors += 64; + IfLabel** labels = (IfLabel**)malloc(m_nMaxSuccessors*sizeof(IfLabel*)); + memcpy(labels, m_labels, (m_nMaxSuccessors-64)*sizeof(IfLabel*)); + IfConfig** targets = (IfConfig**)malloc(m_nMaxSuccessors*sizeof(IfConfig*)); + memcpy(targets, m_targets, (m_nMaxSuccessors-64)*sizeof(IfConfig*)); + + free(m_labels); + free(m_targets); + + m_labels = labels; + m_targets = targets; + } + + m_labels[m_nCurrentSuccessor] = new IfLabel(*label); + m_targets[m_nCurrentSuccessor] = target; + + m_nCurrentSuccessor++; + t_count++; +} + +void IfInteractiveExplorator::run() { + m_source = m_engine->start(); + IfConfig** p = new (IfConfig*); + *p = m_source; + m_path.append(p); + + + while (m_source) { + unsigned int i; + int choice; + +#ifndef win32native + char clear[] = {27,91,72,27,91,50,74,0}; + printf("%s", clear); +#endif + + printf("status: %d steps\n\n", q_count); + m_source->print(stdout); + + q_count++; + + m_nCurrentSuccessor = 0; + m_engine->run(m_source); + + printf("\n\n\ntransitions : \n\n"); + for(i = 0; i<m_nCurrentSuccessor; i++) { + printf("[%d] ", i+1); + IfLabel::setEvPrintFilter(m_evFilter | (1<<IfLabel::NL)); + m_labels[i]->print(stdout); + IfLabel::setEvPrintFilter(0); + printf("\n"); + } + + choice = -1; + while(choice < 0 || choice > (int)m_nCurrentSuccessor) { + printf("\n\nchoice ? "); + if(scanf("%d", &choice) != 1) { + fflush(stdin); + } + } + + if ( choice ) { + m_source = m_targets[choice-1]; + IfConfig** p = new (IfConfig*); + *p = m_source; + m_path.append(p); + } else { + IfLinkedList<IfConfig*>::Node* n = m_path.getLast(); + if( n ) { + n = m_path.getPrev(n); + if( n ) { + m_source = *(m_path.getAt(n)); + m_path.remove(m_path.getLast()); + } + } + } + } +} + +void IfInteractiveExplorator::status() const { +} + + +/* + * + * open explorator + * + */ + +IfOpenExplorator::IfOpenExplorator(const IfEngine* engine, + const char* q_filename, + const char* t_filename, + const char* prism_filename, + const unsigned flags, + const unsigned long evFilter) + : IfExplorator(engine, q_filename, t_filename, prism_filename, flags & ~MS & ~ME, evFilter) { + m_nPathCurrent = -1; +} + +IfOpenExplorator::~IfOpenExplorator() { +} + +void IfOpenExplorator::init() { + m_vPath.clear(); + m_vScenario.clear(); + m_vPath.push_back(m_engine->start()); + m_vScenario.push_back(NULL); + m_nPathCurrent = 0; +} + +void IfOpenExplorator::explore(IfConfig* source, IfLabel* label, + IfConfig* target) { + m_vSuccessors.push_back(target); + m_vSuccLabels.push_back(label); +} + +const IfConfig* IfOpenExplorator::getState() { + if(m_nPathCurrent < 0) + return NULL; + else + return m_vPath[m_nPathCurrent]; +} + +const std::vector<IfLabel*>& IfOpenExplorator::listTransitions() { + m_vSuccessors.clear(); + m_vSuccLabels.clear(); + if(m_nPathCurrent >= 0) +try { + m_engine->run(m_vPath[m_nPathCurrent]); +} catch(IfDynamicError ex) { + // catch Instance Addressing Faults + std::ofstream file("dump.scn"); + file << "<scenario>"; + printScenario(file); + file << "</scenario>"; + file.close(); + exit(1); +} + return m_vSuccLabels; +} + +void IfOpenExplorator::printScenario(std::ostream &out) { + for(unsigned int i = 1; i < m_vScenario.size(); i++) + m_vScenario[i]->printXML(out); + +} + +void IfOpenExplorator::fire(int trno) { + if(trno < 0 || trno >= (int)m_vSuccessors.size()) + return; + m_vPath.erase(m_vPath.begin() + (m_nPathCurrent + 1), m_vPath.end()); + m_vScenario.erase(m_vScenario.begin() + (m_nPathCurrent + 1), m_vScenario.end()); + + m_vPath.push_back(m_vSuccessors[trno]); + m_vScenario.push_back(m_vSuccLabels[trno]); + m_nPathCurrent++; +} + +void IfOpenExplorator::undo() { + if(m_nPathCurrent>=0) m_nPathCurrent--; +} + +void IfOpenExplorator::redo() { + if(m_nPathCurrent>=0 && m_nPathCurrent < (int)m_vPath.size() - 1) m_nPathCurrent++; +} + +void IfOpenExplorator::rewind() { + if(m_nPathCurrent>=0) m_nPathCurrent=0; +} + +void IfOpenExplorator::replay() { + if(m_nPathCurrent>=0) m_nPathCurrent = m_vPath.size() - 1; +} +void IfOpenExplorator::status() const { +} + +/* + * + * debugger + * + */ + +IfDebugger::IfDebugger(const IfEngine* engine, + const char* q_filename, + const char* t_filename, + const char* prism_filename, + const unsigned flags, + const unsigned long evFilter) + : IfExplorator(engine, q_filename, t_filename, prism_filename, flags, evFilter) { + + dfs.stack = NULL; + dfs.depth = 0; +} + +IfDebugger::~IfDebugger() { +} + +void IfDebugger::status() const { + // empty +} + +// + +void IfDebugger::explore(IfConfig* source, IfLabel* label, + IfConfig* target){ + Successor* su = new Successor; + su->state = target; + su->label = label->store(); + su->next = dfs.stack->pending; + dfs.stack->pending = su; +} + +void IfDebugger::init() { + Stack* tt = new Stack; + tt->tail = NULL; + tt->state = m_engine->start(); + tt->state->setMark(STACKED); + tt->running = NULL; + tt->pending = NULL; + + dfs.depth++; + dfs.stack = tt; + + m_engine->run(tt->state); +} + +void IfDebugger::push(Successor* su) { + dfs.stack->running = su; + + Stack* tt = new Stack; + tt->tail = dfs.stack; + tt->state = su->state; + tt->state->setMark(STACKED); + tt->running = NULL; + tt->pending = NULL; + + dfs.depth++; + dfs.stack = tt; + + m_engine->run(tt->state); +} + +void IfDebugger::pop() { + if (dfs.stack->tail == NULL) + return; + + for(Successor* su = dfs.stack->pending; su != NULL; ) { + Successor* s = su; + su = su->next; + delete s; + } + + IfConfig* state = dfs.stack->state; + state->setMark(state->getMark() & (~STACKED)); + + Stack* tt = dfs.stack; + + dfs.stack = dfs.stack->tail; + dfs.depth--; + + delete tt; + + dfs.stack->running = NULL; +} + +// + +void IfDebugger::pending() { + int count = 0; + + printf("\n"); + for(Successor* su = dfs.stack->pending; su != NULL; su = su->next) { + printf("[%c%d] ", (su->state->getMark() & STACKED) ? '*' : ' ', ++count); + su->label->print(stdout); + printf("\n"); + } +} + +void IfDebugger::next(const int k) { + Successor* su = dfs.stack->pending; + int i = 1; + + while (i < k && su != NULL) { + su = su->next; + i++; + } + + if (su == NULL) + printf("\n*** wrong successor index\n"); + + else if (su->state->getMark() & STACKED) { + printf("\n*** cycle detected\n\n"); + + su->label->print(stdout); + printf("\n"); + for(Stack* tt = dfs.stack; tt->state != su->state; tt = tt->tail) { + tt->tail->running->label->print(stdout); + printf("\n"); + } + } + + else + push(su); +} + +void IfDebugger::backward(const int k) { + for(int i = 0; i < k; i++) + pop(); +} + +void IfDebugger::forward(const int k) { + unsigned base = dfs.depth, goal = base + k; + + Successor* su = dfs.stack->pending; + while (dfs.depth < goal) { + + if (su != NULL) { + if (! (su->state->getMark() & STACKED)) { + push(su); + su = dfs.stack->pending; + } + else + su = su->next; + } + + else { + if (dfs.depth > base) { + su = dfs.stack->tail->running->next; + pop(); + } + else { + printf("\n*** depth unreachable\n"); + break; + } + } + } +} + +void IfDebugger::where() const { + printf("\n"); + dfs.stack->state->print(stdout); + printf("\n"); + + readKey(); +} + +void IfDebugger::trace() const { + printf("\n"); + for(Stack* st = dfs.stack; st->tail != NULL; st = st->tail) { + st->tail->running->label->print(stdout); + printf("\n"); + } + printf("\n"); + + readKey(); +} + +void IfDebugger::help() const { + printf("List of available commands:\n\n"); + printf("help -- print this message\n"); + printf("next i -- step on the i-th successor\n"); + printf("back n -- move backward n steps\n"); + printf("fwd n -- move forward n steps\n"); + printf("where -- show the current configuration\n"); + printf("trace -- show the current execution trace\n"); + printf("quit -- exit the debugger\n\n"); + + readKey(); +} + +void IfDebugger::readKey() const { + printf("Press <CR> to continue..."); + getchar(); +} + +void IfDebugger::run() { + printf("IF Debugger - Copyright (C) 2003 Verimag.\n"); fflush(stdout); + + init(); + + for(char command[1024] = ""; + strstr(command, "quit") != command; ) { + int k = -1; + + pending(); + + printf("\n(idbg) "); fgets(command, 1024, stdin); + + if (sscanf(command, "next %d", &k) == 1) + next(k); + if (sscanf(command, "back %d", &k) == 1) + backward(k); + if (sscanf(command, "fwd %d", &k) == 1) + forward(k); + if (strstr(command, "where") == command) + where(); + if (strstr(command, "trace") == command) + trace(); + if (strstr(command, "help") == command) + help(); + } + fflush(stdout); + + backward(100000); // enough ?!?!? +} + +void cleanup(int sig) +{ + fprintf(stderr,"interrupted...\n"); fflush(stderr); + exit(1); +} + +/* + * + * main routine (just in case) + * + */ + +int main(int argc, char* argv[]) { + long cmax = 0; + char* q_filename = NULL; + char* t_filename = NULL; + char* prism_filename = NULL; + enum {BFS, DFS, RANDOM, INTER, XML, DEBUG} traversal = BFS; + unsigned timeFilter = 0; + unsigned priorityFilter = 1; + unsigned flags = 0; + unsigned ind_flags = 0; + unsigned long evFilter = 0; + unsigned hops2 = 0; + + signal(SIGINT,cleanup); /* CTRL-C signal */ + signal(SIGTERM,cleanup); /* software termination signal from kill */ + + if (argc == 1) { + fprintf(stderr, +"*** usage: %s [options], \n\ + where [options] may be: \n\ + .exploration options \n\ + [-bfs|-dfs|-random|-inter|-xml[:port]] : exploration policy : \n\ + - depth first \n\ + - breadth first, \n\ + - random \n\ + - interactive in command line \n\ + - start simulation server (for use with GUI) \n\ + [-cmax integer] : maximal constant used in DBM extrapolation\n\ + [-po] : partial order reduction \n\ + [-ind [om]] : flag events as independent by type (Output, iMport) \n\ + [-fb integer] : find branching states with more than n successors (possibly after PO) \n\ + [-discard] : discard unconsumed/unsaved messages in stable states \n\ + [-tf] : time transition optimisation filter \n\ + [-npf] : do not use dynamic priority functions \n\ + .observer options \n\ + [-cs|-ce] : cut on observer success|error \n\ + [-ms] [-me] : mark transitions entering success/error states \n\ + [-2] : two-hops exploration of observers \n\ + .output options: \n\ + [[-q | -qxml] filename] : output states in <filename> \n\ + [[-t | -txml] filename] : output transitions in <filename> \n\ + [-ln] : generate source line number info \n\ + [-sp] : split transitions in individual events \n\ + [-filter|-show [nsriocfktdmA]] \n\ + : filter/show events by type: iNformal, Set, Reset, Input, \n\ + Output, Call, Fork, Kill, Tick, Deliver, iMport, All \n\ + [-prism filename] : output PRISM Markov Decision Process model in <filename> \n***\n", + argv[0]); + return 1; + } + + IfIterator iterator; + int tcpport = -1; + + for(int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (!strcmp(argv[i], "-bfs")) + traversal = BFS; + else if (!strcmp(argv[i], "-dfs")) + traversal = DFS; + else if (!strcmp(argv[i], "-random")) + traversal = RANDOM; + else if (!strncmp(argv[i], "-xml", 4)) { + traversal = XML; + if(strlen(argv[i]) > 4) + sscanf(argv[i], "-xml:%d", &tcpport); + } else if (!strcmp(argv[i], "-inter")) + traversal = INTER; + else if (!strcmp(argv[i], "-debug")) + traversal = DEBUG; + else if (!strcmp(argv[i], "-cmax")) + cmax = (i == argc - 1) ? 0 : atoi(argv[i+1]); + else if (!strcmp(argv[i], "-po")) + flags |= IfExplorator::PO; + else if (!strcmp(argv[i], "-ind")) { + if(i+1 >= argc) { + fprintf(stderr, "option %s not followed by an event mask\n", argv[i]); + return 1; + } else { + for(char *c = argv[i+1]; *c != '\0'; c++) { + switch(*c) { + case 'o': ind_flags |= 1<<IfEvent::OUTPUT ; break; + case 'm': ind_flags |= 1<<IfEvent::IMPORT ; break; + default : { + fprintf(stderr, "event flag %c not understood\n", *c); + return 1; + } + } + } + } + } + else if (!strcmp(argv[i], "-fb")) { + FIND_BRANCH_MIN = (i == argc - 1) ? 2 : atoi(argv[i+1]); + flags |= IfExplorator::FB; + } + else if (!strcmp(argv[i], "-sp")) + flags |= IfExplorator::SP; + else if (!strcmp(argv[i], "-ln")) + opt_gen_lineno = 1; + else if (!strcmp(argv[i], "-discard")) + opt_discard = 1; + else if (!strcmp(argv[i], "-cs")) + iterator.setCutOnSuccess(); + else if (!strcmp(argv[i], "-ce")) + iterator.setCutOnError(); + else if (!strcmp(argv[i], "-ms")) + flags |= IfExplorator::MS; + else if (!strcmp(argv[i], "-me")) + flags |= IfExplorator::ME; + else if (!strcmp(argv[i], "-2")) + hops2 = 1; + else if (!strcmp(argv[i], "-tf")) + timeFilter = 1; + else if (!strcmp(argv[i], "-npf")) + priorityFilter = 0; + else if (!strcmp(argv[i], "-t")|| !strcmp(argv[i], "-txml")) { + t_filename = (i == argc - 1) ? NULL : argv[i+1]; + opt_txml = strcmp(argv[i], "-t"); + } else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "-qxml")) { + q_filename = (i == argc - 1) ? NULL : argv[i+1]; + opt_qxml = strcmp(argv[i], "-q"); + } else if (!strcmp(argv[i], "-prism")) + prism_filename = (i == argc - 1) ? NULL : argv[i+1]; + else if (!strcmp(argv[i], "-filter") || !strcmp(argv[i], "-show")) { + if(i+1 >= argc) { + fprintf(stderr, "option %s not followed by an event mask\n", argv[i]); + return 1; + } + else { + unsigned long evMask = 0; + for(char *c = argv[i+1]; *c != '\0'; c++) { + switch(*c) { + case 'n': evMask |= 1<<IfEvent::INFORMAL; break; + case 's': evMask |= 1<<IfEvent::SET; break; + case 'r': evMask |= 1<<IfEvent::RESET; break; + case 'i': evMask |= 1<<IfEvent::INPUT; break; + case 'o': evMask |= 1<<IfEvent::OUTPUT; break; + case 'c': evMask |= 1<<IfEvent::CALL; break; + case 'f': evMask |= 1<<IfEvent::FORK; break; + case 'k': evMask |= 1<<IfEvent::KILL; break; + case 't': evMask |= 1<<IfEvent::TICK; break; + case 'd': evMask |= 1<<IfEvent::DELIVER; break; + case 'm': evMask |= 1<<IfEvent::IMPORT; break; + case 'A': evMask |= (1<<28) - 1; break; // last flags used for NL & other options + default : { + fprintf(stderr, "event flag %c not understood\n", *c); + return 1; + } + } + if(!strcmp(argv[i], "-filter")) + evFilter = 0 | evMask; + else + evFilter = ((1<<28)-1) & ~evMask; + } + } + } + else { + fprintf(stderr, "unknown option %s\n", argv[i]); + return 1; + } + } + } + + IfEngine* eng = &iterator; + if (timeFilter) + eng = new IfTimeFilter(eng); + if (priorityFilter) + eng = new IfPriorityFilter(eng); + if(hops2) + eng = new If2HopsEngine(eng); + + if(cmax != 0) + IfDbmTime::restrictExtrapolationZone(cmax); + + if (traversal == BFS) { + IfBfsExplorator bfs(eng, q_filename, t_filename, prism_filename, flags, evFilter); + bfs.run(); + } + + if (traversal == DFS) { + IfDfsExplorator dfs(eng, q_filename, t_filename, prism_filename, flags, ind_flags, evFilter); + dfs.run(); + } + + if (traversal == RANDOM) { + IfRandomExplorator rnd(eng, q_filename, t_filename, prism_filename, flags, evFilter); + rnd.run(); + } + + if (traversal == INTER) { + IfInteractiveExplorator inter(eng, q_filename, t_filename, prism_filename, flags, evFilter); + inter.run(); + } + + if (traversal == XML) { + IfOpenExplorator o(eng, q_filename, t_filename, prism_filename, flags, evFilter); + try { + IfXMLExploratorFacade x(&o); + if(tcpport > 0) + x.serve(tcpport); + else + x.serve(); + } + catch (const XMLException& toCatch) { + fprintf(stderr, "XML module error: %s\n", (char*)toCatch.getMessage()); + return 1; + } + catch (const IfXMLException& toCatch2) { + fprintf(stderr, "XML module error: %s\n", (char*)toCatch2.getDesc()); + return 1; + } + } + + if (traversal == DEBUG) { + IfDebugger debugger(eng, q_filename, t_filename, prism_filename, flags, evFilter); + debugger.run(); + } + + return 0; +} diff --git a/src/simulator-t/explorator.h b/src/simulator-t/explorator.h new file mode 100644 index 0000000000000000000000000000000000000000..91d9645846928c40f486779081d5dc48998aac8a --- /dev/null +++ b/src/simulator-t/explorator.h @@ -0,0 +1,371 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include <vector> + +/* + * + * explorator : defines abstract graph exploration + * + */ + +class IfExplorator : public IfDriver { + + public: + IfExplorator(const IfEngine* engine, + const char* q_filename = NULL, + const char* t_filename = NULL, + const char* prism_filename = NULL, + const unsigned flags = 0, + const unsigned long evFilter = 0); + virtual ~IfExplorator(); + + virtual void run(); + + public: + enum Flag { + PO = 1, // partial order reduction + SP = 2, + ME = 4, // mark transitions entering error states with &error + MS = 8, // mark transitions entering success states with &success + FB = 16 // mark transitions entering success states with &success + }; + + protected: + enum Mark { + REACHED = 0x80000000, + STACKED = 0x40000000, + INDEXMASK = 0x0FFFFFFF + }; + + protected: + virtual void visit(const IfConfig* source, const IfLabel* label, + const IfConfig* target); + virtual void visit(const IfConfig* source); + + protected: + virtual void status() const; + + virtual void alarm(); + + static IfExplorator* XP; +#ifdef win32native + static HANDLE m_hTimerThread; + friend DWORD WINAPI TimerCycle(LPVOID lpParameter); +#else + static inline void cb_alarm(int); +#endif + + protected: + FILE* q_file; // state file + FILE* t_file; // transition file + FILE* prism_file; // PRISM file -> Markov decision process for the IF model + + unsigned q_count; // state counter + unsigned t_count; // transition counter + + unsigned m_flags; // flags + unsigned m_time; // execution time + unsigned m_evFilter; // flags + +}; + +/* + * + * bfs_explorator : breadth-first search exploration + * + */ + +class IfBfsExplorator : public IfExplorator { + + public: + IfBfsExplorator(const IfEngine* engine, + const char* q_filename = NULL, + const char* t_filename = NULL, + const char* prism_filename = NULL, + const unsigned flags = 0, + const unsigned long evFilter = 0); + virtual ~IfBfsExplorator(); + + public: + virtual void explore(IfConfig* source, IfLabel* label, + IfConfig* target); + virtual void run(); + virtual void run(IfConfig* start); + + protected: + struct { + unsigned size; + IfConfig* *queue; + unsigned head, tail; + } bfs; + +}; + +/* + * + * dfs_explorator : depth-first search exploration + * + */ + +class IfDfsExplorator : public IfExplorator { + + public: + IfDfsExplorator(const IfEngine* engine, + const char* q_filename = NULL, + const char* t_filename = NULL, + const char* prism_filename = NULL, + const unsigned flags = 0, + const unsigned ind_flags = 0, + const unsigned long evFilter = 0); + virtual ~IfDfsExplorator(); + + public: + virtual void explore(IfConfig* source, IfLabel* label, + IfConfig* target); + virtual void run(); + virtual void run(IfConfig* start); + + protected: + virtual void status() const; + + unsigned m_ind_flags; + void restrict(); // partial order reduction + + virtual void visit(const IfConfig* source); + virtual void visit(const IfConfig* source, const IfLabel* label, const IfConfig* target) // C++ bug + { IfExplorator::visit(source,label,target); } + + protected: + struct Successor { + IfConfig* state; + IfLabel* label; + Successor* next; + }; + + struct Stack { + IfConfig* state; + IfLabel* label; + Successor* pending; + Stack* tail; + }; + + protected: + struct { + unsigned depth; + Stack* stack; + } dfs; + + private: + virtual void printStackScn(std::ostream& file, Stack* left = NULL); + +}; + +/* + * + * random explorator : random exploration + * + */ + +class IfRandomExplorator : public IfExplorator { + + public: + IfRandomExplorator(const IfEngine* engine, + const char* q_filename = NULL, + const char* t_filename = NULL, + const char* prism_filename = NULL, + const unsigned flags = 0, + const unsigned long evFilter = 0); + virtual ~IfRandomExplorator(); + + public: + virtual void explore(IfConfig* source, IfLabel* label, + IfConfig* target); + virtual void run(); + + protected: + virtual void status() const; + + protected: + struct { + IfConfig* source; + IfLabel* label; + IfConfig* target; + unsigned count; + } random; + +}; + +/* + * + * interactive explorator + * + */ + +class IfInteractiveExplorator : public IfExplorator { + + public: + IfInteractiveExplorator(const IfEngine* engine, + const char* q_filename = NULL, + const char* t_filename = NULL, + const char* prism_filename = NULL, + const unsigned flags = 0, + const unsigned long evFilter = 0); + virtual ~IfInteractiveExplorator(); + + public: + virtual void explore(IfConfig* source, IfLabel* label, + IfConfig* target); + virtual void run(); + + protected: + virtual void status() const; + + protected: + IfConfig* m_source; + IfLabel** m_labels; + IfConfig** m_targets; + IfLinkedList<IfConfig*> m_path; + unsigned m_nMaxSuccessors; + unsigned m_nCurrentSuccessor; +}; + +/* + * + * open explorator + * + */ + +class IfOpenExplorator : public IfExplorator { + +public: + IfOpenExplorator(const IfEngine* engine, + const char* q_filename = NULL, + const char* t_filename = NULL, + const char* prism_filename = NULL, + const unsigned flags = 0, + const unsigned long evFilter = 0); + virtual ~IfOpenExplorator(); + + virtual void explore(IfConfig* source, IfLabel* label, + IfConfig* target); + +public: + virtual void init(); + virtual const IfConfig* getState(); + virtual const std::vector<IfLabel*>& listTransitions(); + virtual void fire(int trno); + virtual void undo(); + virtual void redo(); + virtual void rewind(); + virtual void replay(); + +protected: + virtual void status() const; + virtual void printScenario(std::ostream& file); + +protected: + std::vector<IfConfig*> m_vPath; + std::vector<IfLabel*> m_vScenario; + int m_nPathCurrent; + + std::vector<IfConfig*> m_vSuccessors; + std::vector<IfLabel*> m_vSuccLabels; +}; + +/* + * + * debugger + * + */ + +class IfDebugger: public IfExplorator { + + public: + IfDebugger(const IfEngine* engine, + const char* q_filename = NULL, + const char* t_filename = NULL, + const char* prism_filename = NULL, + const unsigned flags = 0, + const unsigned long evFilter = 0); + virtual ~IfDebugger(); + + public: + virtual void explore(IfConfig* source, IfLabel* label, + IfConfig* target); + virtual void run(); + + protected: + struct Successor { + IfConfig* state; + IfLabel* label; + Successor* next; + }; + + struct Stack { + IfConfig* state; + Successor* pending; + Successor* running; + Stack* tail; + }; + + protected: + virtual void status() const; + virtual void readKey() const; + + virtual void init(); + virtual void push(Successor* su); + virtual void pop(); + + virtual void pending(); + virtual void next(const int); + virtual void backward(const int); + virtual void forward(const int); + virtual void where() const; + virtual void trace() const; + virtual void help() const; + + protected: + struct { + Stack* stack; + unsigned depth; + } dfs; + +}; diff --git a/src/simulator-t/filter.C b/src/simulator-t/filter.C new file mode 100644 index 0000000000000000000000000000000000000000..a2ebed9d23fa56d8358180d42e218d8f0f63ee27 --- /dev/null +++ b/src/simulator-t/filter.C @@ -0,0 +1,236 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" +#include "filter.h" + +/* + * + * time filter implementation + * + */ + +IfTimeFilter::IfTimeFilter(const IfEngine* engine, const IfDriver* driver) + : IfEngine(driver), IfDriver(engine) { + m_head = m_tail = NULL; +} + +IfTimeFilter::~IfTimeFilter() { +} + +IfConfig* IfTimeFilter::start() { + return m_engine->start(); +} + +void IfTimeFilter::run(const IfConfig* source) { + int filter = 0; + + m_engine->run(source); + + IfTime* t_source = getTime(source); + + for(successor* s = m_head; s != NULL; s = s->next) + if (s->label->getAt(0)->getKind() == IfEvent::TICK && + source != s->target) { + IfTime* t_target = getTime(s->target); + if(t_target->include(t_source)) { + filter = 1; + break; + } + } + + while (m_head != NULL) { + successor* s = m_head; + m_head = s->next; + if (!filter || s->label->getAt(0)->getKind() == IfEvent::TICK) + m_driver->explore((IfConfig*) source, s->label, s->target); + delete s; + } + + m_head = m_tail = NULL; +} + +void IfTimeFilter::explore(IfConfig* source, IfLabel* label, + IfConfig* target) { + successor* s = new successor; + s->label = label->store(); + s->target = target; + s->next = NULL; + + if (m_tail == NULL) + m_head = m_tail = s; + else { + m_tail->next = s; + m_tail = s; + } +} + +/* + * + * priority filter implementation + * + */ + +//IfPriorityFilter::Rule IfPriorityFilter::RULE[65536] = {NULL}; + +IfPriorityFilter::IfPriorityFilter(const IfEngine* engine, const IfDriver* driver) + : IfEngine(driver), IfDriver(engine) { + m_head = m_tail = NULL; +} + +IfPriorityFilter::~IfPriorityFilter() { +} + +IfConfig* IfPriorityFilter::start() { + return m_engine->start(); +} + +void IfPriorityFilter::run(const IfConfig* source) { + struct { // extract the set of fireable successors + if_pid_type pid; // and for each one, compute its visibility: + int visible; // non null if no one has priority over it + } fireable[256]; // allow max 256 distinct fireable, enough ? + int count = 0; + int i; + successor* s; + + m_engine->run(source); + + // extract distinct fireable pid's from successors + + for(s = m_head; s != NULL; s = s->next) + if (count == 0 || fireable[count-1].pid != s->label->getPid()) + fireable[count++].pid = s->label->getPid(); + + for(i = 0; i < count; i++) + fireable[i].visible = 1; + + // compute visibilities (n.b. cycles are removed) + + for (i = 0; i < count; i++) + for(int j = 0; j < count; j++) + if (i != j) + for(int k = 0; RULE[k] != NULL && + fireable[j].visible; k++) { + if (RULE[k]((IfConfig*) source, fireable[j].pid, fireable[i].pid)) + break; + if (RULE[k]((IfConfig*) source, fireable[i].pid, fireable[j].pid)) + fireable[j].visible = 0; + } + + // call user driver on visible successors, delete the list + + s = m_head; + for(i = 0; i < count; i++) + while (s != NULL && + s->label->getPid() == fireable[i].pid) { + if (fireable[i].visible) + m_driver->explore((IfConfig*)source, s->label, s->target); + + successor* d = s; + s = s->next; + delete d; + } + + m_head = m_tail = NULL; +} + +void IfPriorityFilter::explore(IfConfig* source, IfLabel* label, + IfConfig* target) { + successor* s = new successor; + s->label = label->store(); + s->target = target; + s->next = NULL; + + if (m_tail == NULL) + m_head = m_tail = s; + else { + m_tail->next = s; + m_tail = s; + } +} + +unsigned if_pid_obs_queue_length(IfConfig *q, const if_pid_type pid) { + IfInstance* inst = q->get(pid); + if(!inst) return 0; + return inst->GetQueue()->GetLength(); +} + +IfMessage* if_pid_obs_queue_get_first(IfConfig *q, if_pid_type pid) { + IfInstance* inst = q->get(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + return (IfMessage*)inst->GetQueue()->getHead(); +} + +IfMessage* if_pid_obs_queue_get_last(IfConfig *q, if_pid_type pid) { + IfInstance* inst = q->get(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + return (IfMessage*)inst->GetQueue()->getTailMessage(); +} + +IfMessage* if_pid_obs_queue_get_at(IfConfig *q, if_pid_type pid, if_integer_type i) { + IfInstance* inst = q->get(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + return (IfMessage*)inst->GetQueue()->getMessageAt(i); +} + +IfMessage* if_pid_obs_queue_remove_first(IfConfig *q, if_pid_type pid) { + IfMessage* res; + IfInstance* inst = q->get(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + inst->RemoveFromQueue(res = (IfMessage*)inst->GetQueue()->getHead()); + return res; +} + +IfMessage* if_pid_obs_queue_remove_last(IfConfig *q, if_pid_type pid) { + IfMessage* res; + IfInstance* inst = q->get(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + inst->RemoveFromQueue(res = (IfMessage*)inst->GetQueue()->getTailMessage()); + return res; +} + +IfMessage* if_pid_obs_queue_remove_at(IfConfig *q, if_pid_type pid, if_integer_type i) { + IfMessage* res; + IfInstance* inst = q->get(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + inst->RemoveFromQueue(res = (IfMessage*)inst->GetQueue()->getMessageAt(i)); + return res; +} diff --git a/src/simulator-t/filter.h b/src/simulator-t/filter.h new file mode 100644 index 0000000000000000000000000000000000000000..d9f1f737021afeb8c7556d45a1471d8f2aeef447 --- /dev/null +++ b/src/simulator-t/filter.h @@ -0,0 +1,136 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * time filter interface + * + */ + +class IfTimeFilter : public IfEngine, public IfDriver { + + public: + IfTimeFilter(const IfEngine* engine, const IfDriver* driver = NULL); + virtual ~IfTimeFilter(); + + public: + virtual IfConfig* start(); + virtual void run(const IfConfig* source); + + public: + virtual void explore(IfConfig* source, IfLabel* label, IfConfig* target); + + protected: + inline IfTime* getTime(const IfConfig* source) const + { return (IfTime*) source->get(if_pid_mk(PROCMAXNUM-1,0)); } + + protected: + struct successor { + IfLabel* label; + IfConfig* target; + successor* next; + } *m_head, *m_tail; + +}; + +/* + * + * priority filter interface (abstract) + * + */ + +class IfPriorityFilter : public IfEngine, public IfDriver { + + public: + // priority rule function type, returns + // != 0 : x has greater priority than y in source + // == 0 : x and y are not comparable in source + typedef int (*Rule)(IfConfig* source, if_pid_type x, if_pid_type y); + + public: + // priority rules (this member could be made private but as long + // as we will consider only one global set of rules, it works + static Rule *RULE; + + public: + IfPriorityFilter(const IfEngine* engine, const IfDriver* driver = NULL); + virtual ~IfPriorityFilter(); + + public: + virtual IfConfig* start(); + virtual void run(const IfConfig* source); + + public: + virtual void explore(IfConfig* source, IfLabel* label, IfConfig* target); + + protected: + struct successor { + IfLabel* label; + IfConfig* target; + successor* next; + } *m_head, *m_tail; + + // problem : consider the situation where there are only two + // transitions, one eager another lazy, and the lazy one having greater + // priority. The filtering will remove the eager one so we end up with one + // lazy successor. Do we need the tick transition here ? I think so, + // but it was previously removed because of the eager (non prioritary) + // transition. So, the model is too restricted. + + // remark: 2) the problem above does not exist: if the lazy ones has + // priority over the eager one this does not mean that time could ellapse! + + // remark: 1) if the model does not contain lazy or + // delayable transitions, the problem does not occur + + // solution: if ones detect that there are only lazy transitions + // enabled after filtering, and there is no tick-transition, we have to + // add it. We have to mark (simulator) transitions in order to see + // their urgency (eager, lazy). + +}; + +unsigned if_pid_obs_queue_length(IfConfig *q, const if_pid_type pid); +IfMessage* if_pid_obs_queue_get_first(IfConfig *q, if_pid_type pid); +IfMessage* if_pid_obs_queue_get_last(IfConfig *q, if_pid_type pid); +IfMessage* if_pid_obs_queue_get_at(IfConfig *q, if_pid_type pid, if_integer_type i); +IfMessage* if_pid_obs_queue_remove_first(IfConfig *q, if_pid_type pid); +IfMessage* if_pid_obs_queue_remove_last(IfConfig *q, if_pid_type pid); +IfMessage* if_pid_obs_queue_remove_at(IfConfig *q, if_pid_type pid, if_integer_type i); diff --git a/src/simulator-t/xmlexplorator.C b/src/simulator-t/xmlexplorator.C new file mode 100644 index 0000000000000000000000000000000000000000..36330554310b8787ef9592def6454356fe8bee3c --- /dev/null +++ b/src/simulator-t/xmlexplorator.C @@ -0,0 +1,371 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#ifdef win32native +#include "winsock2.h" +#include "sys/types.h" +#include "io.h" +#else +#include <sys/types.h> +#include <sys/socket.h> +#include <unistd.h> +#include <netinet/in.h> +#include <errno.h> +#include <signal.h> +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#endif + +// APACHE Xerces headers +#include <xercesc/util/PlatformUtils.hpp> +#include <xercesc/parsers/AbstractDOMParser.hpp> +#include <xercesc/dom/DOM.hpp> +#include <xercesc/util/XMLString.hpp> +#include <xercesc/framework/MemBufInputSource.hpp> +#include <xercesc/framework/Wrapper4InputSource.hpp> + +XERCES_CPP_NAMESPACE_USE + +#include <stdio.h> +#include <iostream> +#include <sstream> + +// project headers +#include "simulator.h" +#include "explorator.h" +#include "xmlexplorator.h" + +int IfXMLExploratorFacade::XML_PLATFORM_INITIALIZED = 0; +const char* IfXMLExploratorFacade::XMLHEADER = "<?xml version = \"1.0\" encoding = \"ISO-8859-1\" standalone = \"yes\" ?>"; + +IfXMLExploratorFacade::IfXMLExploratorFacade(IfOpenExplorator* pExplorator) { + m_pExplorator = pExplorator; + m_nXMLBufMax = XMLBUFGROWTH; + m_psXMLBuf = (char*)malloc(m_nXMLBufMax); + + setupXMLParser(); +} + +void IfXMLExploratorFacade::setupXMLParser() { + if(!XML_PLATFORM_INITIALIZED) { + // Initialize the XML4C system + XMLPlatformUtils::Initialize(); + XML_PLATFORM_INITIALIZED = 1; + } + + // Instantiate the DOM parser. + static XMLCh gLS[100]; + XMLString::transcode("LS", gLS, 99); + DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(gLS); + m_pDOMParser = ((DOMImplementationLS*)impl)->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0); + + // optionally you can set some features on this builder + if (m_pDOMParser->getDomConfig()->canSetParameter(XMLUni::fgDOMValidate, false)) + m_pDOMParser->getDomConfig()->setParameter(XMLUni::fgDOMValidate, false); + if (m_pDOMParser->getDomConfig()->canSetParameter(XMLUni::fgDOMNamespaces, false)) + m_pDOMParser->getDomConfig()->setParameter(XMLUni::fgDOMNamespaces, false); + if (m_pDOMParser->getDomConfig()->canSetParameter(XMLUni::fgXercesSchema, false)) + m_pDOMParser->getDomConfig()->setParameter(XMLUni::fgXercesSchema, false); + if (m_pDOMParser->getDomConfig()->canSetParameter(XMLUni::fgXercesSchemaFullChecking, false)) + m_pDOMParser->getDomConfig()->setParameter(XMLUni::fgXercesSchemaFullChecking, false); + // enable datatype normalization - default is off + if (m_pDOMParser->getDomConfig()->canSetParameter(XMLUni::fgDOMDatatypeNormalization, true)) + m_pDOMParser->getDomConfig()->setParameter(XMLUni::fgDOMDatatypeNormalization, true); + + // And create our error handler and install it + DOMExploratorErrorHandler errorHandler; + m_pDOMParser->getDomConfig()->setParameter(XMLUni::fgDOMErrorHandler, &errorHandler); +} + +IfXMLExploratorFacade::~IfXMLExploratorFacade() { +} + +IfXMLExploratorFacade::SOCK_STATUS IfXMLExploratorFacade::serve(int port) { + SOCK_STATUS res; + + if( (res = init(port)) != S_OKAY) return res; + res = run(); + close(m_nSocket); + return res; +} + +IfXMLExploratorFacade::SOCK_STATUS IfXMLExploratorFacade::init(int port) { + SOCKET servSocket; + int opt = 1; + +#ifdef win32native + WSAData wsaData; + WSAStartup(2, &wsaData); +#endif + + /* setup the sock_addr data structure */ + struct sockaddr_in socketInfo; + memset(&socketInfo, 0, sizeof(socketInfo)); + socketInfo.sin_family = AF_INET; + socketInfo.sin_port = htons( port ); + socketInfo.sin_addr.s_addr = htonl( INADDR_ANY ); + + /* create the new socket */ + servSocket = socket( AF_INET, SOCK_STREAM, 0 ); + setsockopt(servSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)); + + if(servSocket == INVALID_SOCKET ) + return S_CONERR; + + /* bind the socket */ + if( bind( servSocket, (struct sockaddr *)&socketInfo, sizeof( socketInfo ) ) == SOCKET_ERROR ) { + close(servSocket); + IfXMLException ex("Socket bind() error."); + throw ex; + } + + /* set up the socket for listening */ + if( listen( servSocket, 10 ) == SOCKET_ERROR ) { + close(servSocket); + IfXMLException ex("Socket listen() error."); + throw ex; + } + + struct sockaddr_in client; + socklen_t addrlen = sizeof(struct sockaddr); + m_nSocket = accept(servSocket, (struct sockaddr*) &client, &addrlen); + //close(servSocket); + if(m_nSocket == INVALID_SOCKET) { + IfXMLException ex ("Socket accept() error."); + throw ex; + } + + return S_OKAY; +} + +IfXMLExploratorFacade::SOCK_STATUS IfXMLExploratorFacade::run() { + SOCK_STATUS res; + + while(1) { + if( (res = readXML()) != S_OKAY ) + return res; + executeXML(); + } + +} + +IfXMLExploratorFacade::SOCK_STATUS IfXMLExploratorFacade::readXML() { + char sPDULength[9]; + int nPDULength; + int nBytes, nTotBytes = 0; + + while(nTotBytes < 8) { + nBytes = recv(m_nSocket, sPDULength + nTotBytes, 8 - nTotBytes, 0); +if(nBytes != SOCKET_ERROR) write(1, sPDULength + nTotBytes, nBytes); + if(nBytes == 0 || nBytes == SOCKET_ERROR) + return S_CONERR; + nTotBytes += nBytes; + } + sPDULength[nTotBytes]=0; + nPDULength = atoi(sPDULength); + + if(nPDULength + 1 > m_nXMLBufMax) { + m_nXMLBufMax += XMLBUFGROWTH; + m_psXMLBuf = (char*)realloc(m_psXMLBuf, m_nXMLBufMax); + } + + nTotBytes = 0; + while(nTotBytes < nPDULength) { + nBytes = recv(m_nSocket, m_psXMLBuf + nTotBytes, nPDULength - nTotBytes, 0); +if(nBytes != SOCKET_ERROR) write(1, m_psXMLBuf + nTotBytes, nBytes); + if(nBytes == 0 || nBytes == SOCKET_ERROR) + return S_CONERR; + nTotBytes += nBytes; + } + m_psXMLBuf[nTotBytes] = 0; + + return S_OKAY; +} + +void IfXMLExploratorFacade::executeXML() { + try { + parseXML(); + executeXML0(); + if(m_pDocument) delete m_pDocument; + } catch(IfXMLException ex) { + fprintf(stderr, "XML messaging error: %s\n", ex.getDesc()); + } +} + +void IfXMLExploratorFacade::parseXML() { + //puts(m_psXMLBuf); + m_pDocument = NULL; + MemBufInputSource memBufIS((const XMLByte*)m_psXMLBuf, strlen(m_psXMLBuf), "id", false); + Wrapper4InputSource memBufDOMIS(&memBufIS, false); + try { + m_pDocument = m_pDOMParser->parse(&memBufDOMIS); + } catch (...) { + char c[4096] = "Parse error : "; + strncat(c, m_psXMLBuf, 4070); + IfXMLException ex(c); + throw ex; + } +} + +void IfXMLExploratorFacade::executeXML0() { + DOMElement* command = m_pDocument->getDocumentElement(); + _XS _xs(command->getTagName()); + const char* commandName = _xs; + + if(!strcmp(commandName,"IFSInit")) { + m_pExplorator->init(); + sendOK(); + } else if(!strcmp(commandName,"IFSFire")) { + executeFire(command); + sendOK(); + } else if(!strcmp(commandName,"IFSUndo")) { + m_pExplorator->undo(); + sendOK(); + } else if(!strcmp(commandName,"IFSRedo")) { + m_pExplorator->redo(); + sendOK(); + } else if(!strcmp(commandName,"IFSRewind")) { + m_pExplorator->rewind(); + sendOK(); + } else if(!strcmp(commandName,"IFSReplay")) { + m_pExplorator->replay(); + sendOK(); + } else if(!strcmp(commandName,"IFSGetState")) + executeGetState(command); + else if(!strcmp(commandName,"IFSListTransitions")) + executeListTransitions(command); + else { // unknown command + IfXMLException ex("Unknown command"); + throw ex; + } + fprintf(stderr, "\nCommand OK\n"); +} + +void IfXMLExploratorFacade::executeFire(DOMElement* c) { + _SX _sx("trno"); + if(c->hasAttribute(_sx)) { + _XS _xs(c->getAttribute(_sx)); + m_pExplorator->fire(atoi(_xs)); + } else { + IfXMLException ex("Malformed comand"); + throw ex; + } +} + +void IfXMLExploratorFacade::executeGetState(DOMElement* c) { + std::stringstream res; + res << XMLHEADER; + const IfConfig* s = m_pExplorator->getState(); + if(s) s->printXML(res); + else res << "<void/>"; + res << '\0'; + sendXMLAnswer(res.str().c_str()); +} + +void IfXMLExploratorFacade::executeListTransitions(DOMElement* c) { + std::stringstream res; + res << XMLHEADER; + const std::vector<IfLabel*>& tv = m_pExplorator->listTransitions(); + res << "<IfTransitionList>\n"; + for(std::vector<IfLabel*>::const_iterator iter = tv.begin(); iter != tv.end(); iter++) + (*iter)->printXML(res); + res << "</IfTransitionList>\n"; + res << '\0'; + sendXMLAnswer(res.str().c_str()); +} + +void IfXMLExploratorFacade::sendXMLAnswer(const char* xml) { + char PDUHead[9]; + int l; + sprintf(PDUHead, "%8d", l = strlen(xml)); + send(m_nSocket, PDUHead, 8, 0); + send(m_nSocket, xml, l, 0); +/*write(1, "\n-response-\n", strlen("\n-response-\n")); +write(1, PDUHead, 8); +write(1, xml, l); +write(1, "\n-response-\n", strlen("\n-response-\n"));*/ +} + +void IfXMLExploratorFacade::sendOK() { + sendXMLAnswer("<IFSOk/>"); +} + +/* + * + * DOMExploratorErrorHandler + * + */ + +DOMExploratorErrorHandler::DOMExploratorErrorHandler() : + fSawErrors(false) +{ +} + +DOMExploratorErrorHandler::~DOMExploratorErrorHandler() +{ +} + +bool DOMExploratorErrorHandler::handleError(const DOMError& domError) +{ + fSawErrors = true; + /*if (domError.getSeverity() == DOMError::DOM_SEVERITY_WARNING) + cerr << "\nWarning at file "; + else if (domError.getSeverity() == DOMError::DOM_SEVERITY_ERROR) + cerr << "\nError at file "; + else + cerr << "\nFatal Error at file "; + + cerr << StrX(domError.getLocation()->getURI()) + << ", line " << domError.getLocation()->getLineNumber() + << ", char " << domError.getLocation()->getColumnNumber() + << "\n Message: " << StrX(domError.getMessage()) << endl; + */ + return true; +} + +void DOMExploratorErrorHandler::resetErrors() +{ + fSawErrors = false; +} + +inline bool DOMExploratorErrorHandler::getSawErrors() const +{ + return fSawErrors; +} diff --git a/src/simulator-t/xmlexplorator.h b/src/simulator-t/xmlexplorator.h new file mode 100644 index 0000000000000000000000000000000000000000..00db6547aecada1a42e3920c39289ec42b950720 --- /dev/null +++ b/src/simulator-t/xmlexplorator.h @@ -0,0 +1,193 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * proxy for open explorator, controlled via XML messaging + * + */ + +#ifndef _WINSOCKAPI_ + #define SOCKET int +#else + #define socklen_t int +#endif + +#define XMLBUFGROWTH 256 +#define XMLDEFAULTPORT 15555 + +// APACHE Xerces headers +#include <xercesc/util/PlatformUtils.hpp> +#include <xercesc/dom/DOM.hpp> +#include <xercesc/dom/DOMErrorHandler.hpp> +#include <xercesc/util/XMLString.hpp> +#include <xercesc/framework/MemBufInputSource.hpp> +#include <xercesc/framework/Wrapper4InputSource.hpp> +#include <xercesc/util/PlatformUtils.hpp> +#include <xercesc/sax/HandlerBase.hpp> + +XERCES_CPP_NAMESPACE_USE + +class IfXMLExploratorFacade { + +public: + IfXMLExploratorFacade(IfOpenExplorator* pExplorator); + ~IfXMLExploratorFacade(); + void setupXMLParser(); + + typedef enum { S_OKAY, S_CONERR, S_PROTERR, S_PROTDISCONNECT } SOCK_STATUS; + SOCK_STATUS serve(int port = XMLDEFAULTPORT); + +protected: + SOCK_STATUS init(int port); + SOCK_STATUS run(); + SOCK_STATUS readXML(); + void executeXML(); + void parseXML(); + void executeXML0(); + void executeFire(DOMElement* c); + void executeGetState(DOMElement* c); + void executeListTransitions(DOMElement* c); + + void sendXMLAnswer(const char* xml); + void sendOK(); + +public: + static const char* XMLHEADER; + +protected: + IfOpenExplorator* m_pExplorator; + SOCKET m_nSocket; + + char* m_psXMLBuf; + int m_nXMLBufMax; + + static int XML_PLATFORM_INITIALIZED; + DOMLSParser *m_pDOMParser; + XERCES_CPP_NAMESPACE::DOMDocument *m_pDocument; +}; + +class DOMExploratorErrorHandler : public DOMErrorHandler +{ +public: + DOMExploratorErrorHandler(); + ~DOMExploratorErrorHandler(); + + bool getSawErrors() const; + bool handleError(const DOMError& domError); + void resetErrors(); + +private : + // This is set if we get any errors, + // and is queryable via a getter method. + bool fSawErrors; +}; + +class IfXMLException +{ +public: + IfXMLException(const char* desc, bool copy=true) { m_psDesc = (desc?strdup(desc) : NULL); } + IfXMLException(IfXMLException& other) { m_psDesc = (other.getDesc()?strdup(other.getDesc()) : NULL); } + ~IfXMLException() { if(m_psDesc) free(m_psDesc); } + + const char* getDesc() const { return m_psDesc; } + +private: + IfXMLException() { } + +protected: + char* m_psDesc; +}; + +/* + * + * Conversion from XMLCh to const char* + * + */ + +#ifdef _XS //Windows - clash with useless macro +#undef _XS +#endif + +class _XS +{ +public : + _XS(const XMLCh* const toTranscode) { + fLocalForm = XMLString::transcode(toTranscode); + } + ~_XS() { + XMLString::release(&fLocalForm); + } + const char* localForm() const { + return fLocalForm; + } + operator const char* () const { + return fLocalForm; + } + +private : + char* fLocalForm; +}; + +/* + * + * Conversion from const char* to XMLCh + * + */ + +class _SX +{ +public : + _SX(const char* const toTranscode) { + fLocalForm = XMLString::transcode(toTranscode); + } + ~_SX() { + XMLString::release(&fLocalForm); + } + XMLCh* localForm() const { + return fLocalForm; + } + operator XMLCh* () const { + return fLocalForm; + } + +private : + XMLCh* fLocalForm; +}; diff --git a/src/simulator/Makefile b/src/simulator/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2055ce8e983a6250b93bc151e9fe907855277f9a --- /dev/null +++ b/src/simulator/Makefile @@ -0,0 +1,91 @@ +# +# +# IF-Toolset - Copyright (C) UGA - CNRS - G-INP +# +# by Marius - Iulian - Susanne - Laurent - Joseph +# Bozga - Ober - Graf - Mounier - Sifakis +# +# This software is a computer program whose purpose is to simulate, +# explore and model-check real-time systems represented using the IF - +# intermediate format - language. This software package contains +# sources, documentation, and examples. +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the +# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following +# URL "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided +# only with a limited warranty and the software's author, the holder of +# the economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards +# their requirements in conditions enabling the security of their +# systems and/or data to be ensured and, more generally, to use and +# operate it in the same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +.SUFFIXES: +.SUFFIXES: .C .i .o + + SRC = ifzone.C \ + object.C \ + queue.C \ + instance.C \ + xtime.C \ + monitor.C \ + buffer.C \ + config.C \ + label.o \ + engine.C \ + iterator.C \ + simulator.C \ + observer.C + + OBJ = $(OBJDIR)/ifzone.o \ + $(OBJDIR)/object.o \ + $(OBJDIR)/queue.o \ + $(OBJDIR)/instance.o \ + $(OBJDIR)/xtime.o \ + $(OBJDIR)/monitor.o \ + $(OBJDIR)/buffer.o \ + $(OBJDIR)/config.o \ + $(OBJDIR)/label.o \ + $(OBJDIR)/engine.o \ + $(OBJDIR)/iterator.o \ + $(OBJDIR)/simulator.o \ + $(OBJDIR)/observer.o + + LIB = libsimulator.a + +############################# + +build: $(LIB) + + +install: build + -mv -f $(LIB) $(IF)/bin + +clean: + -rm -f $(OBJ) $(LIB) + +############################# + +$(LIB) : $(OBJ) + $(AR) cql $@ $(OBJ) + +$(OBJDIR)/%.o: %.C + $(CC) $(CFLAGS) -o $(OBJDIR)/$*.o $*.C diff --git a/src/simulator/base.h b/src/simulator/base.h new file mode 100644 index 0000000000000000000000000000000000000000..90ad035896b33c57165d3f7105bb1e148d9d211e --- /dev/null +++ b/src/simulator/base.h @@ -0,0 +1,57 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * interface of basic types + * + */ + +typedef int if_boolean_type; + +typedef int if_integer_type; + +typedef float if_real_type; + +typedef unsigned if_pid_type; + +typedef int if_clock_type; + +typedef unsigned if_void_type; diff --git a/src/simulator/base.i b/src/simulator/base.i new file mode 100644 index 0000000000000000000000000000000000000000..14028662126f18c608246cbda9c780650b101444 --- /dev/null +++ b/src/simulator/base.i @@ -0,0 +1,264 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * boolean : boolean implementation + * + */ + +#define if_boolean_false 0 + +#define if_boolean_true 1 + + +#define if_boolean_copy(x,y) x=y + +#define if_boolean_compare(x,y) (x)-(y) + +#define if_boolean_print(x,f) fprintf(f,"%c",x?'t':'f') + +#define if_boolean_print_xml(x,b) b << "<boolean value='" << (x?"true":"false") << "' />" + +#define if_boolean_reset(x) x=0 + +#define if_boolean_iterate(x) for(x=0;x<2;x++) + + +#define if_boolean_not(x) !(x) + +#define if_boolean_and(x,y) (x)&&(y) + +#define if_boolean_or(x,y) (x)||(y) + + +#define if_boolean_eq(x,y) (x)==(y) + +#define if_boolean_ne(x,y) (x)!=(y) + + +/* + * + * integer : integer implementation + * + */ + +#define if_integer_copy(x,y) x=y + +#define if_integer_compare(x,y) (x)-(y) + +#define if_integer_print(x,f) fprintf(f,"%d",x) + +#define if_integer_print_xml(x,b) b << "<integer value='" << x << "' />" + +#define if_integer_reset(x) x=0 + +// #define if_integer_iterate(x) : undefined + + +#define if_integer_mult(x,y) (x)*(y) + +#define if_integer_div(x,y) (x)/(y) + +#define if_integer_mod(x,y) (x)%(y) + +#define if_integer_plus(x,y) (x)+(y) + +#define if_integer_minus(x,y) (x)-(y) + + +#define if_integer_uplus(x) +(x) + +#define if_integer_uminus(x) -(x) + + +#define if_integer_lt(x,y) (x)<(y) + +#define if_integer_le(x,y) (x)<=(y) + +#define if_integer_ge(x,y) (x)>=(y) + +#define if_integer_gt(x,y) (x)>(y) + + +#define if_integer_eq(x,y) (x)==(y) + +#define if_integer_ne(x,y) (x)!=(y) + + +/* + * + * real : real implementation + * + */ + +#define if_real_copy(x,y) x=y + +#define if_real_compare(x,y) ((x)==(y))?0:((x)<(y))?-1:1 + +#define if_real_print(x,f) fprintf(f,"%f",x) + +#define if_real_print_xml(x,b) b << "<real value='" << x << "' />" + +#define if_real_reset(x) x=0.0 + +// #define if_real_iterate(x) : undefined + + +#define if_real_mult(x,y) (x)*(y) + +#define if_real_div(x,y) (x)/(y) + +#define if_real_mod(x,y) (x)%(y) + +#define if_real_plus(x,y) (x)+(y) + +#define if_real_minus(x,y) (x)-(y) + + +#define if_real_uplus(x) +(x) + +#define if_real_uminus(x) -(x) + + +#define if_real_lt(x,y) (x)<(y) + +#define if_real_le(x,y) (x)<=(y) + +#define if_real_ge(x,y) (x)>=(y) + +#define if_real_gt(x,y) (x)>(y) + + +#define if_real_eq(x,y) (x)==(y) + +#define if_real_ne(x,y) (x)!=(y) + + +/* + * + * pid : pid implementation + * + */ + +#define PROCMASK 0xFFFF0000 + +#define if_pid_proc(x) (x)>>16 + +#define if_pid_idet(x) ((x)&0xFFFF) + + +#define if_pid_nil 0 + + +#define if_pid_copy(x,y) x=y + +#define if_pid_compare(x,y) (x)-(y) + +#define if_pid_print(x,f) \ + fprintf(f,"{%s}%d", IfInstance::PROCNAME[if_pid_proc(x)],if_pid_idet(x)) + +#define if_pid_print_xml(x,b) \ + b << "<pid name='" << IfInstance::PROCNAME[if_pid_proc(x)] << "' no='" << if_pid_idet(x) << "' />" + +#define if_pid_sprint(x,s) \ + sprintf(s,"{%s}%d", IfInstance::PROCNAME[if_pid_proc(x)],if_pid_idet(x)) + +#define if_pid_reset(x) x=0 + +#define if_pid_iterate(x) \ + for(x=0; x<1; x++) + + +#define if_pid_eq(x,y) (x)==(y) + +#define if_pid_ne(x,y) (x)!=(y) + + +#define if_pid_mk(p,x) ((p)<<16)|(x) + + +/* + * + * clock : clock implementation + * + */ + +#define if_clock_copy(x,y) x=y + +#define if_clock_compare(x,y) (x)-(y) + +#define if_clock_print(x,f) fprintf(f,"%d",x) + +#define if_clock_print_xml(x,b) b << "<clock id='" << x << "' />" + +#define if_clock_sprint(x,f) sprintf(f,"%d",x) + +#define if_clock_reset(x) \ + if (IfInstance::STATUS & IfInstance::CREATE) \ + x=-1; \ + else \ + IfInstance::ITERATOR->reset(&x) + +// #define if_clock_iterate(x) : undefined + + +/* + * + * void : void implementation + * + */ + +#define if_void_copy(x,y) x=0 + +#define if_void_compare(x,y) 0 + +#define if_void_print(x,f) fprintf(f,"{}") + +#define if_void_print_xml(x,b) b << "<void/>" + +#define if_void_reset(x) x=0 + +#define if_void_iterate(x) + +#define if_void_eq(x,y) 1 + +#define if_void_ne(x,y) 0 + diff --git a/src/simulator/buffer.C b/src/simulator/buffer.C new file mode 100644 index 0000000000000000000000000000000000000000..9432afef5e1f634687eb04b5ec09dbb8d64a27dc --- /dev/null +++ b/src/simulator/buffer.C @@ -0,0 +1,350 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * buffer : implements abstract communication buffers + * + */ + +IfBuffer::IfBuffer(const if_pid_type from, const if_pid_type to, + const unsigned flags, + const int lower, const int upper, + const if_pid_type pid, + const IfQueue* queue, + const double lossProba) + : IfInstance(pid, (IfQueue*) queue) { + m_from = from; + m_to = to; + m_flags = flags; + m_lower = lower; + m_upper = upper; + + m_lossProba = lossProba; +} + +IfBuffer::IfBuffer(const IfBuffer& buffer) + : IfInstance(buffer) { + m_from = buffer.m_from; + m_to = buffer.m_to; + m_flags = buffer.m_flags; + m_lower = buffer.m_lower; + m_upper = buffer.m_upper; + + m_lossProba = buffer.m_lossProba; +} + +IfBuffer::~IfBuffer() { +} + +int IfBuffer::guard(const IfMessage* message) const { + int enabled = 0; + + IfTime::Constraint constraints[3] = {{0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}; + + if (is(URGENT)) + enabled = ITERATOR->guard(constraints, EAGER); + + if (is(DELAY) || is(RATE)) { + constraints[0].x = 0; + constraints[0].y = message->getWait(); + constraints[0].k = -2 * m_lower + 1; + + constraints[1].x = message->getWait(); + constraints[1].y = 0; + constraints[1].k = 2 * m_upper + 1; + + enabled = ITERATOR->guard(constraints, DELAYABLE); + } + + return enabled; +} + +void IfBuffer::dispatch(const IfMessage* message) const { + + IfMessage* m = message->copy(); + m->setDestination(0); + m->setWait(-1); + + if (is(PEER)) { // peer-to-peer transmission + if (is(LOSSY)) + ITERATOR->record(); + + if ((message->getDestination() & PROCMASK) == m_to) + ITERATOR->deliver(message->getDestination(), m); + if (is(LOSSY)) + ITERATOR->trace(IfEvent::PROBABILITY, m_pid, "", 1-getLossProba()); + ITERATOR->step(); + + if (is(LOSSY)) { + ITERATOR->restore(); + // loss + ITERATOR->trace(IfEvent::LOSS, m_pid, ""); + ITERATOR->trace(IfEvent::PROBABILITY, m_pid, "", getLossProba()); + ITERATOR->step(); + ITERATOR->forget(); + } + } + + if (is(MULTICAST)) { // multicast transmission + if (is(LOSSY)) { + // not yet implement : buffer : dispatch : lossy multicast + } + else { + int n = ITERATOR->fetchPid(m_to); + for(int i = 0; i < n; i++) { + if_pid_type pid = ITERATOR->getPid(i); + ITERATOR->deliver(pid, m); + } + ITERATOR->step(); + } + } + + if (is(UNICAST)) { // unicast transmission. !!! modified for lossy -> (n destinations => n loss transitions) + int n = ITERATOR->fetchPid(m_to); + ITERATOR->record(); + for(int i = 0; i < n; i++) { + if_pid_type pid = ITERATOR->getPid(i); + + ITERATOR->deliver(pid, m); + if (is(LOSSY)) + ITERATOR->trace(IfEvent::PROBABILITY, m_pid, "", 1-getLossProba()); + ITERATOR->step(); + ITERATOR->restore(); + + if (is(LOSSY)) { + // loss + ITERATOR->trace(IfEvent::LOSS, m_pid, ""); + ITERATOR->trace(IfEvent::PROBABILITY, m_pid, "", getLossProba()); + ITERATOR->step(); + ITERATOR->restore(); + } + } + ITERATOR->forget(); + } + + delete m; +} + +void IfBuffer::copy(const IfInstance* instance) { + IfBuffer* buffer = (IfBuffer*) instance; + IfInstance::copy(instance); + m_from = buffer->m_from; + m_to = buffer->m_to; + m_flags = buffer->m_flags; + m_lower = buffer->m_lower; + m_upper = buffer->m_upper; + + m_lossProba = buffer->m_lossProba; +} + +void IfBuffer::deliver(const IfMessage* message) { + // abstract : redefined +} + +void IfBuffer::reset() { + if_clock_type wait = -1; + + if (is(DELAY)) { + for(IfQueue* queue = m_queue; queue != IfQueue::NIL; + queue = (IfQueue*) queue->getTail()) { + wait = queue->getHead()->getWait(); + ITERATOR->reset(&wait); + } + } + if (is(RATE)) { + if (m_queue != IfQueue::NIL) { + wait = m_queue->getHead()->getWait(); + ITERATOR->reset(&wait); + } + } + + m_queue = IfQueue::NIL; +} + +/* + * + * fifo buffer : implements fifo communication buffers + * + */ + +IfFifoBuffer::IfFifoBuffer(const if_pid_type from, const if_pid_type to, + const unsigned flags, + const int lower, const int upper, + const if_pid_type pid, + const IfQueue* queue, + const double lossProba) + : IfBuffer(from, to, flags, lower, upper, pid, queue, lossProba) { +} + +IfFifoBuffer::IfFifoBuffer(const IfFifoBuffer& fifo) + : IfBuffer(fifo) { +} + +IfFifoBuffer::~IfFifoBuffer() { +} + +void IfFifoBuffer::deliver(const IfMessage* message) { + + if_clock_type wait = -1; + + if (is(DELAY)) + ITERATOR->set(&wait, 0, m_pid); + if (is(RATE)) { + if (m_queue == IfQueue::NIL) + ITERATOR->set(&wait, 0, m_pid); + else + wait = m_queue->getHead()->getWait(); + } + + ((IfMessage*)message)->setWait(wait); // brrrr... + + IfInstance::deliver(message); +} + +void IfFifoBuffer::iterate(IfIterator* iter) { + IfMessage* message = NULL; + if_clock_type wait = -1; + + ITERATOR = iter; + + if (m_queue == IfQueue::NIL) + return; + + message = (IfMessage*) m_queue->getHead(); + if (guard(message) == 0) + return; + + m_queue = (IfQueue*) m_queue->getTail(); + wait = message->getWait(); + + if (is(DELAY)) + ITERATOR->reset(&wait); + if (is(RATE)) { + if (m_queue == IfQueue::NIL) + ITERATOR->reset(&wait); + else + ITERATOR->set(&wait, 0, m_pid); + } + + ITERATOR->trace(IfEvent::DELIVER, m_pid, "", m_pid, message); + + dispatch(message); +} + + + +/* + * + * multiset buffer : implements multiset communication buffers + * + */ + +IfMultisetBuffer::IfMultisetBuffer(const if_pid_type from, const if_pid_type to, + const unsigned flags, + const int lower, const int upper, + const if_pid_type pid, + const IfQueue* queue, + const double lossProba) + : IfBuffer(from, to, flags, lower, upper, pid, queue, lossProba) { +} + +IfMultisetBuffer::IfMultisetBuffer(const IfMultisetBuffer& multiset) + : IfBuffer(multiset) { +} + +IfMultisetBuffer::~IfMultisetBuffer() { +} + +void IfMultisetBuffer::deliver(const IfMessage* message) { + if_clock_type wait = -1; + + if (is(DELAY)) + ITERATOR->set(&wait, 0, m_pid); + if (is(RATE)) { + if (m_queue == IfQueue::NIL) + ITERATOR->set(&wait, 0, m_pid); + else + wait = m_queue->getHead()->getWait(); + } + + ((IfMessage*)message)->setWait(wait); // brrrr... + + m_queue = m_queue->insert(message->store()); + +} + +void IfMultisetBuffer::iterate(IfIterator* iterator) { + IfMessage* message = NULL; + if_clock_type wait = -1; + + ITERATOR = iterator; + + for(IfQueue* queue = m_queue; queue != IfQueue::NIL; + queue = (IfQueue*) queue->getTail()) { + + message = (IfMessage*) queue->getHead(); + if (guard(message) == 0) + continue; + + m_queue = m_queue->remove(message); + wait = message->getWait(); + + if (is(DELAY)) + ITERATOR->reset(&wait); + if (is(RATE)) { + if (m_queue == IfQueue::NIL) + ITERATOR->reset(&wait); + else + ITERATOR->set(&wait, 0, m_pid); + } + + ITERATOR->trace(IfEvent::DELIVER, m_pid, ""); + + dispatch(message); + + ITERATOR->restore(); + } + +} diff --git a/src/simulator/buffer.h b/src/simulator/buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..0b487565964881347f7e91f5e72e3b35c087ff6a --- /dev/null +++ b/src/simulator/buffer.h @@ -0,0 +1,161 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + + + +enum { // same as in signalroute.h + + FIFO = 0x00000001, // queueing policies + MULTISET = 0x00000002, + + RELIABLE = 0x00000100, // reliability + LOSSY = 0x00000200, + + PEER = 0x00010000, // dispacthing policies + MULTICAST = 0x00020000, + UNICAST = 0x00040000, + + URGENT = 0x01000000, // delaying modes + DELAY = 0x02000000, + RATE = 0x04000000 +}; + +/* + * + * buffer : defines abstract communication buffers + * + */ + +class IfBuffer : public IfInstance { + + public: + IfBuffer(const if_pid_type, const if_pid_type, + const unsigned = 0, + const int = -1, const int = -1, + const if_pid_type = 0, + const IfQueue* = IfQueue::NIL, + const double lossProba = 0); + IfBuffer(const IfBuffer&); + virtual ~IfBuffer(); + + public: + inline if_pid_type getFrom() const + { return m_from; } + inline if_pid_type getTo() const + { return m_to; } + inline int getLower() const + { return m_lower; } + inline int getUpper() const + { return m_upper; } + inline int is(const unsigned flag) const + { return m_flags & flag; } + inline double getLossProba() const + { return m_lossProba; } + + public: + virtual int guard(const IfMessage*) const; + virtual void dispatch(const IfMessage*) const; + virtual void copy(const IfInstance*); + + public: + virtual void deliver(const IfMessage*); + + public: + virtual void reset(); + + protected: + if_pid_type m_from; // from process class + if_pid_type m_to; // to process class + unsigned m_flags; // buffer flags + int m_lower; // transit time lower bound + int m_upper; // transit time upper bound + + double m_lossProba; + +}; + + +/* + * + * fifo buffer : defines fifo communication buffers + * + */ + +class IfFifoBuffer : public IfBuffer { + + public: + IfFifoBuffer(const if_pid_type, const if_pid_type, + const unsigned = 0, + const int = -1, const int = -1, + const if_pid_type = 0, + const IfQueue* = IfQueue::NIL, + const double lossProba = 0); + IfFifoBuffer(const IfFifoBuffer&); + virtual ~IfFifoBuffer(); + + public: + virtual void deliver(const IfMessage*); + virtual void iterate(IfIterator*); + +}; + +/* + * + * multiset buffer : defines multiset communication buffers (bag) + * + */ + +class IfMultisetBuffer : public IfBuffer { + + public: + IfMultisetBuffer(const if_pid_type, const if_pid_type, + const unsigned = 0, + const int = -1, const int = -1, + const if_pid_type = 0, + const IfQueue* = IfQueue::NIL, + const double lossProba = 0); + IfMultisetBuffer(const IfMultisetBuffer&); + virtual ~IfMultisetBuffer(); + + public: + virtual void deliver(const IfMessage*); + virtual void iterate(IfIterator*); + +}; diff --git a/src/simulator/config.C b/src/simulator/config.C new file mode 100644 index 0000000000000000000000000000000000000000..ee4b9fd7b9944180540f954950f8a9be71dc15ff --- /dev/null +++ b/src/simulator/config.C @@ -0,0 +1,175 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * config : implements arbitrary configurations + * + */ + +IfConfig::IfConfig(unsigned size) + : IfObject(), m_chunks(size) { + m_mark = 0; +} + +IfConfig::IfConfig(const IfConfig& config) + : IfObject(config), m_chunks(config.m_chunks) { + m_mark = config.m_mark; +} + +IfConfig::~IfConfig() { +} + +int IfConfig::isObsSuccess() const +{ + unsigned len = m_chunks.getLength(); + for(unsigned i = 0; i<len; i++) { + Chunk* chunk = getAt(i); + for(int j = 0; j < CONFIGCHUNKSIZE; j++) { + IfInstance* instance = chunk->getAt(j); + if (instance) { + if( instance->isObsSuccess() ) + return 1; + } + } + } + return 0; +} + +int IfConfig::isObsError() const +{ + unsigned len = m_chunks.getLength(); + for(unsigned i = 0; i<len; i++) { + Chunk* chunk = getAt(i); + for(int j = 0; j < CONFIGCHUNKSIZE; j++) { + IfInstance* instance = chunk->getAt(j); + if (instance) { + if( instance->isObsError() ) + return 1; + } + } + } + return 0; +} + +int IfConfig::isCut() const +{ + unsigned len = m_chunks.getLength(); + for(unsigned i = 0; i<len; i++) { + Chunk* chunk = getAt(i); + for(int j = 0; j < CONFIGCHUNKSIZE; j++) { + IfInstance* instance = chunk->getAt(j); + if (instance) { + if( instance->isCut() ) + return 1; + } + } + } + return 0; +} + +int IfConfig::compare(const IfConfig* config) const { + return m_chunks.compare(&config->m_chunks); +} + +long unsigned IfConfig::hash(const unsigned long base) const { + return m_chunks.hash(base); +} + +IfConfig* IfConfig::copy() const { + return new IfConfig(*this); +} + +void IfConfig::print(FILE* file) const { + unsigned len = m_chunks.getLength(); + for(unsigned i = 0; i<len; i++) { + Chunk* chunk = getAt(i); + for(int j = 0; j < CONFIGCHUNKSIZE; j++) { + IfInstance* instance = chunk->getAt(j); + if (instance) { + instance->print(file); + fprintf(file, "\n"); + } + } + } +} + +void IfConfig::printXML(std::ostream& buf) const { + buf << "<IfConfig>\n"; + unsigned len = m_chunks.getLength(); + for(unsigned i = 0; i<len; i++) { + Chunk* chunk = getAt(i); + for(int j = 0; j < CONFIGCHUNKSIZE; j++) { + IfInstance* instance = chunk->getAt(j); + if (instance) { + instance->printXML(buf); + buf << "\n"; + } + } + } + buf << "</IfConfig>\n"; +} + +IfInstance* IfConfig::get(const if_pid_type pid) const { + IfInstance* result = NULL; + unsigned len = m_chunks.getLength(); + for(unsigned i = 0; i < len && !result; i++) { + Chunk* chunk = getAt(i); + for(int j = 0; j < CONFIGCHUNKSIZE && !result; j++) { + IfInstance* instance = chunk->getAt(j); + if (instance && instance->getPid() == pid) + result = instance; + if (instance && instance->getPid() > pid) + break; + } + } + return result; +} + +IfTime* IfConfig::getTime() const { + return (IfTime*) get(if_pid_mk(PROCMAXNUM-1, 0)); +} + +IMPLEMENT_STORE(IfConfig::Chunk, "chunk") + +IMPLEMENT_STORE(IfConfig,"config") + diff --git a/src/simulator/config.h b/src/simulator/config.h new file mode 100644 index 0000000000000000000000000000000000000000..14e76bc581f763419c72fb22b7e557dc3014aa48 --- /dev/null +++ b/src/simulator/config.h @@ -0,0 +1,90 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * config : defines configurations of arbitrary size + * + */ + +#define CONFIGCHUNKSIZE 6 + +class IfConfig : public IfObject { + + public: + IfConfig(const unsigned = 0); + IfConfig(const IfConfig&); + virtual ~IfConfig(); + + public: + struct Chunk : public IfChunk<IfInstance,CONFIGCHUNKSIZE> { + Chunk() : IfChunk<IfInstance,CONFIGCHUNKSIZE>() {} + + DECLARE_STORE(Chunk) + }; + + public: + inline Chunk* getAt(const int i) const + { return m_chunks.getAt(i); } + inline void setAt(const int i, const Chunk* chunk) + { m_chunks.setAt(i, (Chunk*) chunk); } + inline unsigned getMark() const + { return m_mark; } + inline void setMark(const unsigned mark) + { m_mark = mark; } + + IfInstance* get(const if_pid_type) const; + IfTime* getTime() const; + + public: + int isObsSuccess() const; + int isObsError() const; + int isCut() const; + + public: + DECLARE_STORABLE(IfConfig) + DECLARE_STORE(IfConfig) + + protected: + IfString<Chunk> m_chunks; + unsigned m_mark; + +}; + diff --git a/src/simulator/engine.C b/src/simulator/engine.C new file mode 100644 index 0000000000000000000000000000000000000000..e469301d2cac415fe602173ff1502f9aeafaf977 --- /dev/null +++ b/src/simulator/engine.C @@ -0,0 +1,89 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * abstract engine implementation + * + */ + +IfEngine::IfEngine() { + m_driver = NULL; +} + +IfEngine::IfEngine(const IfDriver* driver) { + m_driver = (IfDriver*) driver; +} + +IfEngine::~IfEngine() { +} + +IfConfig* IfEngine::start() { + // abstract + return NULL; +} + +void IfEngine::run(const IfConfig* source) { + // abstract +} + +/* + * + * abstract driver implementation + * + */ + +IfDriver::IfDriver() { + m_engine = NULL; +} + +IfDriver::IfDriver(const IfEngine* engine) { + m_engine = (IfEngine*) engine; m_engine->setDriver(this); +} + +IfDriver::~IfDriver() { +} + +void IfDriver::explore(IfConfig* source, IfLabel* label, + IfConfig* target) { + // abstract +} diff --git a/src/simulator/engine.h b/src/simulator/engine.h new file mode 100644 index 0000000000000000000000000000000000000000..57262efff9db28beb9b7dccc7e5be4b031d51358 --- /dev/null +++ b/src/simulator/engine.h @@ -0,0 +1,96 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract engine interface + * + */ + +class IfEngine { + + public: + IfEngine(); + IfEngine(const IfDriver* driver); + virtual ~IfEngine(); + + public: + inline IfDriver* getDriver() const + { return m_driver; } + inline void setDriver(const IfDriver* driver) + { m_driver = (IfDriver*) driver; } + + public: + virtual IfConfig* start(); + virtual void run(const IfConfig* source); + + protected: + IfDriver* m_driver; + +}; + +/* + * + * abstract driver interface + * + */ + +class IfDriver { + + public: + IfDriver(); + IfDriver(const IfEngine* engine); + virtual ~IfDriver(); + + public: + inline IfEngine* getEngine() const + { return m_engine; } + inline void setEngine(const IfEngine* engine) + { m_engine = (IfEngine*) engine; m_engine->setDriver(this); } + + public: + virtual void explore(IfConfig* source, + IfLabel* label, + IfConfig* target); + + protected: + IfEngine* m_engine; + +}; diff --git a/src/simulator/ifzone.C b/src/simulator/ifzone.C new file mode 100644 index 0000000000000000000000000000000000000000..1d9f05d1168d86b8cba142c44a4a8bffcedaa5fa --- /dev/null +++ b/src/simulator/ifzone.C @@ -0,0 +1,1201 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * Zone / Clock DBM Implementation + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <memory.h> + +#include "ifzone.h" + + +/* +----------------------------------------------------------------------- +Value Implementation +----------------------------------------------------------------------- +*/ + +void if_print_bound(if_type_bound bound, FILE* file){ + if (bound == IF_BOUND_INFTY) + fprintf(file, " +oo"); + else + fprintf(file, "%4d", bound); +} + + + + +/* +----------------------------------------------------------------------- +Vector / Vector Table Implementation +----------------------------------------------------------------------- +*/ + +if_type_vector if_create_vector(unsigned dimension){ + return (if_type_vector) malloc(sizeof(if_type_bound) * dimension); +} + +if_type_vector if_duplicate_vector(if_type_vector vector, unsigned dimension){ + if_type_vector result = if_create_vector(dimension); + memcpy(result, vector, sizeof(if_type_bound) * dimension); + return result; +} + +void if_delete_vector(if_type_vector vector, unsigned){ + free(vector); +} + +void if_copy_vector(if_type_vector destination, if_type_vector source, unsigned dimension){ + memcpy(destination, source, sizeof(if_type_bound) * dimension); +} + +int if_compare_vector(if_type_vector vector1, if_type_vector vector2, unsigned dimension){ + return memcmp(vector1, vector2, sizeof(if_type_bound) * dimension); +} + +unsigned long if_hash_vector(if_type_vector vector, unsigned dimension, unsigned base){ + unsigned long h = 0; + for(unsigned i = 0; i < dimension; i++) + h += (((long) vector[i]) << (3 * i % 17)); + if (h < 0) + h = -h; + return h % base; +} + +void if_print_vector(if_type_vector vector, unsigned dimension, FILE* file){ + fprintf(file, "["); + for(unsigned i = 0; i < dimension; i++) { + if_print_bound(vector[i], file); + fprintf(file, "%s", i == dimension - 1 ? "]" : " "); + } +} + +/* +----------------------------------------------------------------------- +*/ + +#define if_vector_table_size 8191 + +typedef struct if_struct_vector_node { + unsigned dimension; + if_type_vector_list list; + struct if_struct_vector_node * next; +} * if_type_vector_node; + +static struct { + struct { + struct { + if_type_vector_node node; + unsigned count; + } entry[if_vector_table_size]; + unsigned count; + } table; +} if_vector; + +/* +----------------------------------------------------------------------- +*/ + +void if_init_vector_table(){ + for(int i = 0; i < if_vector_table_size; i++) { + if_vector.table.entry[i].node = NULL; + if_vector.table.entry[i].count = 0; + } + if_vector.table.count = 0; +} + +void if_exit_vector_table(){ + for(int i = 0; i < if_vector_table_size; i++) { + while (if_vector.table.entry[i].node) { + if_type_vector_node node = if_vector.table.entry[i].node; + while (node->list) { + if_type_vector_list list = node->list; + node->list = list->next; + free(list->vector); + free(list); + } + if_vector.table.entry[i].node = node->next; + free(node); + } + } +} + +void if_info_vector_table(FILE* file){ + unsigned min, max; + min = max = if_vector.table.entry[0].count; + for(int i = 1; i < if_vector_table_size; i++){ + if (min > if_vector.table.entry[i].count) + min = if_vector.table.entry[i].count; + if (max < if_vector.table.entry[i].count) + max = if_vector.table.entry[i].count; + } + fprintf(file, "%d vectors stored (%d/max, %d/min, %d/avg)\n", + if_vector.table.count, max, min, + if_vector.table.count / if_vector_table_size); +} + +if_type_vector if_put_vector(if_type_vector vector, unsigned dimension){ + if_type_vector_node node = NULL; + if_type_vector_list list = NULL; + unsigned long hash = if_hash_vector(vector, dimension, if_vector_table_size); + for(node = if_vector.table.entry[hash].node; node != NULL; node = node->next) + if (node->dimension == dimension) + break; + if (node == NULL) { + node = (if_type_vector_node) malloc(sizeof(if_struct_vector_node)); + node->dimension = dimension; + node->list = NULL; + node->next = if_vector.table.entry[hash].node; + if_vector.table.entry[hash].node = node; + } + for(list = node->list; list != NULL; list = list->next) + if (! if_compare_vector(list->vector, vector, dimension)) + break; + if (list == NULL) { + list = (if_type_vector_list) malloc(sizeof(if_struct_vector_list)); + list->vector = if_duplicate_vector(vector, dimension); + list->next = node->list; + node->list = list; + if_vector.table.entry[hash].count++; + if_vector.table.count++; + } + return list->vector; +} + + + + +/* +----------------------------------------------------------------------- +Matrix / Matrix Table Implementation +----------------------------------------------------------------------- +*/ + +if_type_matrix if_create_matrix(unsigned dimension){ + return (if_type_matrix) malloc(sizeof(if_type_vector) * dimension); +} + +if_type_matrix if_duplicate_matrix(if_type_matrix matrix, unsigned dimension){ + if_type_matrix result = if_create_matrix(dimension); + memcpy(result, matrix, sizeof(if_type_vector) * dimension); + return result; +} + +void if_delete_matrix(if_type_matrix matrix, unsigned dimension){ + free(matrix); +} + +void if_copy_matrix(if_type_matrix destination, if_type_matrix source, unsigned dimension){ + memcpy(destination, source, sizeof(if_type_vector) * dimension); +} + +int if_compare_matrix(if_type_matrix matrix1, if_type_matrix matrix2, unsigned dimension){ + return memcmp(matrix1, matrix2, sizeof(if_type_vector) * dimension); +} + +unsigned long if_hash_matrix(if_type_matrix matrix, unsigned dimension, unsigned base){ + unsigned long h = 0; + for(unsigned i = 0; i < dimension; i++) + h += ((((long) matrix[i]) >> 4) << (3 * i % 17)); + if (h < 0) + h = -h; + return h % base; +} + +void if_print_matrix(if_type_matrix matrix, unsigned dimension, FILE* file){ + for(unsigned i = 0; i < dimension; i++){ + if_print_vector(matrix[i], dimension, file); + fprintf(file, "\n"); + } +} + +/* +----------------------------------------------------------------------- +*/ + +#define if_matrix_table_size 8191 + +#define if_matrix_max_dimension 64 + +typedef struct if_struct_matrix_node { + unsigned dimension; + if_type_matrix_list list; + struct if_struct_matrix_node * next; +} * if_type_matrix_node; + +static struct { + struct { + struct { + if_type_matrix_node node; + unsigned count; + } entry[if_matrix_table_size]; + unsigned count; + } table; + struct { + if_type_matrix lines; + if_type_matrix matrix; + } cache; + if_type_matrix extrapolation; +} if_matrix; + +/* +----------------------------------------------------------------------- +*/ + +void if_init_matrix_table(){ + int i; + + for(i = 0; i < if_matrix_table_size; i++) { + if_matrix.table.entry[i].node = NULL; + if_matrix.table.entry[i].count = 0; + } + if_matrix.table.count = 0; + if_matrix.cache.lines = if_create_matrix(if_matrix_max_dimension); + for(i = 0; i < if_matrix_max_dimension; i++) + if_matrix.cache.lines[i] = if_create_vector(if_matrix_max_dimension); + if_matrix.cache.matrix = if_create_matrix(if_matrix_max_dimension); + if_matrix.extrapolation = if_universal_zone(); +} + +void if_exit_matrix_table(){ + int i; + + for(i = 0; i < if_matrix_table_size; i++) { + while (if_matrix.table.entry[i].node) { + if_type_matrix_node node = if_matrix.table.entry[i].node; + while (node->list) { + if_type_matrix_list list = node->list; + node->list = list->next; + free(list->matrix); + free(list); + } + if_matrix.table.entry[i].node = node->next; + free(node); + } + } + for(i = 0; i < if_matrix_max_dimension; i++) + if_delete_vector(if_matrix.cache.lines[i], if_matrix_max_dimension); + if_delete_matrix(if_matrix.cache.lines, if_matrix_max_dimension); + if_delete_matrix(if_matrix.cache.matrix, if_matrix_max_dimension); +} + +void if_info_matrix_table(FILE* file){ + unsigned min, max; + min = max = if_matrix.table.entry[0].count; + for(int i = 1; i < if_matrix_table_size; i++){ + if (min > if_matrix.table.entry[i].count) + min = if_matrix.table.entry[i].count; + if (max < if_matrix.table.entry[i].count) + max = if_matrix.table.entry[i].count; + } + fprintf(file, "%d matrixes stored (%d/max, %d/min, %d/avg)\n", + if_matrix.table.count, max, min, + if_matrix.table.count / if_matrix_table_size); +} + +if_type_matrix if_put_matrix(if_type_matrix matrix, unsigned dimension){ + if_type_matrix_node node = NULL; + if_type_matrix_list list = NULL; + unsigned long hash = if_hash_matrix(matrix, dimension, if_matrix_table_size); + for(node = if_matrix.table.entry[hash].node; node != NULL; node = node->next) + if (node->dimension == dimension) + break; + if (node == NULL) { + node = (if_type_matrix_node) malloc(sizeof(if_struct_matrix_node)); + node->dimension = dimension; + node->list = NULL; + node->next = if_matrix.table.entry[hash].node; + if_matrix.table.entry[hash].node = node; + } + for(list = node->list; list != NULL; list = list->next) + if (! if_compare_matrix(list->matrix, matrix, dimension)) + break; + if (list == NULL) { + list = (if_type_matrix_list) malloc(sizeof(if_struct_matrix_list)); + list->matrix = if_duplicate_matrix(matrix, dimension); + list->next = node->list; + node->list = list; + if_matrix.table.entry[hash].count++; + if_matrix.table.count++; + } + return list->matrix; +} + + + + +/* +----------------------------------------------------------------------- +Zone Implementation +----------------------------------------------------------------------- +*/ + + +if_type_zone if_empty_zone(){ + return NULL; +} + +if_type_zone if_universal_zone(){ + if_type_zone result; + if_matrix.cache.lines[0][0] = 0; + if_matrix.cache.matrix[0] = if_put_vector(if_matrix.cache.lines[0], 1); + result = if_put_matrix(if_matrix.cache.matrix, 1); + return result; +} + +int if_is_empty_zone(if_type_zone zone){ + return zone == NULL; +} + +int if_is_universal_zone(if_type_zone zone){ + unsigned universal = 1, dimension = zone[0][0] + 1; + + for(unsigned i = 0; i < dimension && universal; i++) + for(unsigned j = 0; j < dimension && universal; j++) + if (i != j && zone[i][j] < IF_BOUND_INFTY) + universal = 0; + return universal; +} + +int if_clock_in_zone(if_type_zone zone, int clock) { + int in = 0; + if (!zone) + return 0; + for(int k = 1; k <= zone[0][0] && !in; k++) + if (clock == zone[k][k]) + in = 1; + return in; +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_clkcmp_zone(int clock1, int clock2, int value, int sign) { + if_type_zone result; + if (clock1 == clock2) + result = ((sign == IF_SIGN_LT && 0 < value) || + (sign == IF_SIGN_LE && 0 <= value)) ? + if_universal_zone() : if_empty_zone(); + else { + if_type_bound bound = if_make_bound(value,sign); + if (clock1 == 0 || clock2 == 0) { + if_matrix.cache.lines[0][0] = 1; + if_matrix.cache.lines[0][1] = clock1 == 0 ? bound : IF_BOUND_INFTY; + if_matrix.cache.lines[1][0] = clock2 == 0 ? bound : IF_BOUND_INFTY; + if_matrix.cache.lines[1][1] = clock1 ? clock1 : clock2; + if_matrix.cache.matrix[0] = if_put_vector(if_matrix.cache.lines[0], 2); + if_matrix.cache.matrix[1] = if_put_vector(if_matrix.cache.lines[1], 2); + result = if_put_matrix(if_matrix.cache.matrix, 2); + } + else { + if_matrix.cache.lines[0][0] = 2; + if_matrix.cache.lines[0][1] = IF_BOUND_INFTY; + if_matrix.cache.lines[0][2] = IF_BOUND_INFTY; + if_matrix.cache.lines[1][0] = IF_BOUND_INFTY; + if_matrix.cache.lines[1][1] = clock1 < clock2 ? clock1 : clock2; + if_matrix.cache.lines[1][2] = clock1 < clock2 ? bound : IF_BOUND_INFTY; + if_matrix.cache.lines[2][0] = IF_BOUND_INFTY; + if_matrix.cache.lines[2][1] = clock2 < clock1 ? bound : IF_BOUND_INFTY; + if_matrix.cache.lines[2][2] = clock2 < clock1 ? clock1 : clock2; + if_matrix.cache.matrix[0] = if_put_vector(if_matrix.cache.lines[0], 3); + if_matrix.cache.matrix[1] = if_put_vector(if_matrix.cache.lines[1], 3); + if_matrix.cache.matrix[2] = if_put_vector(if_matrix.cache.lines[2], 3); + result = if_put_matrix(if_matrix.cache.matrix, 3); + } + } + return result; +} + +if_type_zone if_clklt_zone(int clock1, int clock2, int value){ + return if_clkcmp_zone(clock1, clock2, value, IF_SIGN_LT); +} + +if_type_zone if_clkle_zone(int clock1, int clock2, int value){ + return if_clkcmp_zone(clock1, clock2, value, IF_SIGN_LE); +} + +if_type_zone if_clkge_zone(int clock1, int clock2, int value){ + return if_clkle_zone(clock2, clock1, -value); +} + +if_type_zone if_clkgt_zone(int clock1, int clock2, int value){ + return if_clklt_zone(clock2, clock1, -value); +} + +if_type_zone if_clkeq_zone(int clock1, int clock2, int value){ + return if_intersect_zone(if_clkle_zone(clock1, clock2, value), + if_clkle_zone(clock2, clock1, -value)); +} + +/* +----------------------------------------------------------------------- +*/ + +int if_normalize_zone(if_type_zone zone){ + + for(int k = 0; k <= zone[0][0]; k++) + for(int i = 0; i <= zone[0][0]; i++) + if (i != k && zone[i][k] < IF_BOUND_INFTY) { + + if (zone[k][i] < IF_BOUND_INFTY && + if_add_bound(zone[i][k],zone[k][i]) < if_make_bound(0,IF_SIGN_LE)) + return 0; + + for (int j = 0; j <= zone[0][0]; j++) + if (i != j && j != k && zone[k][j] < IF_BOUND_INFTY && + if_add_bound(zone[i][k], zone[k][j]) < zone[i][j] ) + zone[i][j] = if_add_bound(zone[i][k], zone[k][j]); + + } + return 1; + +} + +/* +----------------------------------------------------------------------- +*/ + +int if_extrapolate_zone(if_type_zone zone, if_type_zone ezone){ + + for(int i = 0, ie = 0; i <= zone[0][0]; i++, ie++) { + for(; i != 0 && ie <= ezone[0][0] && ezone[ie][ie] < zone[i][i]; ie++); + if (i == 0 || (ie <= ezone[0][0] && ezone[ie][ie] == zone[i][i])) + for(int j = 0, je = 0; j <= zone[0][0]; j++, je++) { + for(; j != 0 && je <= ezone[0][0] && ezone[je][je] < zone[j][j]; je++); + if (j == 0 || (je <= ezone[0][0] && ezone[je][je] == zone[j][j])) + if (i != j && zone[i][j] < IF_BOUND_INFTY){ + + if (ezone[ie][je] < IF_BOUND_INFTY && + zone[i][j] > ezone[ie][je]) { + zone[i][j] = IF_BOUND_INFTY; + continue; + } + if (ezone[je][ie] < IF_BOUND_INFTY && + zone[i][j] < if_complement_bound(ezone[je][ie])) { + zone[i][j] = if_complement_bound(ezone[je][ie]); + continue; + } + + } + } + } + return 1; + +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_intersect_zone(if_type_zone zone1, if_type_zone zone2){ + unsigned dimension1, dimension2, dimension, k; + unsigned i, i1, i2; + + if (if_is_empty_zone(zone1) || if_is_empty_zone(zone2)) + return if_empty_zone(); + + dimension1 = zone1[0][0] + 1; + dimension2 = zone2[0][0] + 1; + k = 1; + for(i1 = 1, i2 = 1; i1 < dimension1 || i2 < dimension2;) { + for(; i1 < dimension1 && (i2 == dimension2 || + zone1[i1][i1] < zone2[i2][i2]); i1++, k++) + if_matrix.cache.lines[k][k] = zone1[i1][i1]; + for(; i2 < dimension2 && (i1 == dimension1 || + zone2[i2][i2] < zone1[i1][i1]); i2++, k++) + if_matrix.cache.lines[k][k] = zone2[i2][i2]; + for(; i1 < dimension1 && (i2 < dimension2 && + zone1[i1][i1] == zone2[i2][i2]); i1++, i2++, k++) + if_matrix.cache.lines[k][k] = zone1[i1][i1]; + } + + dimension = k; + if_matrix.cache.lines[0][0] = dimension - 1; + + for(i = 0; i < dimension; i++) + for(unsigned j = 0; j < dimension; j++) + if (i != j) + if_matrix.cache.lines[i][j] = IF_BOUND_INFTY; + + for(i1 = 0, i = 0; i1 < dimension1; i1++, i++) { + for(; i1 != 0 && if_matrix.cache.lines[i][i] != zone1[i1][i1]; i++); + for(unsigned j1 = 0, j = 0; j1 < dimension1; j1++, j++) { + for(; j1 != 0 && if_matrix.cache.lines[j][j] != zone1[j1][j1]; j++); + if (i1 != j1) + if_matrix.cache.lines[i][j] = zone1[i1][j1]; + } + } + + for(i2 = 0, i = 0; i2 < dimension2; i2++, i++) { + for(; i2 != 0 && if_matrix.cache.lines[i][i] != zone2[i2][i2]; i++); + for(unsigned j2 = 0, j = 0; j2 < dimension2; j2++, j++) { + for(; j2 != 0 && if_matrix.cache.lines[j][j] != zone2[j2][j2]; j++); + if (i2 != j2) + if_matrix.cache.lines[i][j] = + if_min_bound(if_matrix.cache.lines[i][j],zone2[i2][j2]); + } + } + + if (!if_normalize_zone(if_matrix.cache.lines)) + return if_empty_zone(); + + if_extrapolate_zone(if_matrix.cache.lines, if_matrix.extrapolation); + + for(i = 0; i < dimension; i++) + if_matrix.cache.matrix[i] = if_put_vector(if_matrix.cache.lines[i], dimension); + return if_put_matrix(if_matrix.cache.matrix, dimension); + +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_exists_zone(if_type_zone zone, int clock){ + unsigned dimension, k, i, j; + + if (if_is_empty_zone(zone)) + return zone; + + dimension = zone[0][0] + 1; + for(k = 1; k < dimension; k++) + if (zone[k][k] == clock) + break; + if (k == dimension) + return zone; + + for(i = 0; i < k; i++) { + for(j = 0; j < k; j++) + if_matrix.cache.lines[i][j] = zone[i][j]; + for(j = k + 1; j < dimension; j++) + if_matrix.cache.lines[i][j-1] = zone[i][j]; + } + for(i = k + 1; i < dimension; i++) { + for(j = 0; j < k; j++) + if_matrix.cache.lines[i-1][j] = zone[i][j]; + for(j = k + 1; j < dimension; j++) + if_matrix.cache.lines[i-1][j-1] = zone[i][j]; + } + if_matrix.cache.lines[0][0]--; + dimension--; + + for(i = 0; i < dimension; i++) + if_matrix.cache.matrix[i] = if_put_vector(if_matrix.cache.lines[i], dimension); + return if_put_matrix(if_matrix.cache.matrix, dimension); + +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_set_zone(if_type_zone zone, int clock, int value){ + unsigned dimension, k, i, j; + + if (if_is_empty_zone(zone)) + return zone; + + dimension = zone[0][0] + 1; + for(k = 1; k < dimension; k++) + if (zone[k][k] == clock) + break; + if (k == dimension) + return if_intersect_zone(zone, if_clkeq_zone(clock, 0, value)); + + for(i = 0; i < dimension; i++) + for(j = 0; j < dimension; j++) + if_matrix.cache.lines[i][j] = zone[i][j]; + for(i = 0; i < dimension; i++) + if (i != k) + if_matrix.cache.lines[i][k] = if_matrix.cache.lines[k][i] = IF_BOUND_INFTY; + if_matrix.cache.lines[k][0] = if_make_bound(value, IF_SIGN_LE); + if_matrix.cache.lines[0][k] = if_make_bound(-value, IF_SIGN_LE); + + if (!if_normalize_zone(if_matrix.cache.lines)) + return if_empty_zone(); + + if_extrapolate_zone(if_matrix.cache.lines, if_matrix.extrapolation); + + for(i = 0; i < dimension; i++) + if_matrix.cache.matrix[i] = if_put_vector(if_matrix.cache.lines[i], dimension); + return if_put_matrix(if_matrix.cache.matrix, dimension); + +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_round_zone(if_type_zone zone, int direction, int sign) { + unsigned dimension, rounded = 1, i, j; + + if (if_is_empty_zone(zone)) + return zone; + + dimension = zone[0][0] + 1; + for(i = 1; i < dimension && rounded; i++) { + if ((direction & 1) && // forward / right + zone[i][0] < IF_BOUND_INFTY && + if_sign_bound(zone[i][0]) != sign) + rounded = 0; + if ((direction & 2) && // backward / left + zone[0][i] < IF_BOUND_INFTY && + if_sign_bound(zone[0][i]) != sign) + rounded = 0; + } + + if (rounded) + return zone; + + for(i = 0; i < dimension; i++) + for(j = 0; j < dimension; j++) + if_matrix.cache.lines[i][j] = zone[i][j]; + for(i = 1; i < dimension; i++) { + if ((direction & 1) && + zone[i][0] < IF_BOUND_INFTY) + if_matrix.cache.lines[i][0] = + if_make_bound(if_value_bound(zone[i][0]), sign); + if ((direction & 2) && + zone[0][i] < IF_BOUND_INFTY) + if_matrix.cache.lines[0][i] = + if_make_bound(if_value_bound(zone[0][i]), sign); + } + + if (!if_normalize_zone(if_matrix.cache.lines)) + return if_empty_zone(); + + if_extrapolate_zone(if_matrix.cache.lines, if_matrix.extrapolation); + + for(i = 0; i < dimension; i++) + if_matrix.cache.matrix[i] = if_put_vector(if_matrix.cache.lines[i], dimension); + return if_put_matrix(if_matrix.cache.matrix, dimension); + +} + +/* * */ + +if_type_zone if_open_right_zone(if_type_zone zone) { + return if_round_zone(zone, 1, IF_SIGN_LT); +} + +if_type_zone if_close_right_zone(if_type_zone zone) { + return if_round_zone(zone, 1, IF_SIGN_LE); +} + +if_type_zone if_open_left_zone(if_type_zone zone) { + return if_round_zone(zone, 2, IF_SIGN_LT); +} + +if_type_zone if_close_left_zone(if_type_zone zone) { + return if_round_zone(zone, 2, IF_SIGN_LE); +} + +/* * */ + +if_type_zone if_open_zone(if_type_zone zone) { + return if_open_right_zone(zone); +} + +if_type_zone if_close_zone(if_type_zone zone) { + return if_close_right_zone(zone); +} + + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_backward_zone(if_type_zone zone){ + unsigned dimension, backward = 1, i; + + if (if_is_empty_zone(zone)) + return zone; + + dimension = zone[0][0] + 1; + for(i = 1; i < dimension && backward; i++) + if (zone[0][i] < IF_BOUND_INFTY) + backward = 0; + if (backward) + return zone; + + for(i = 0; i < dimension; i++) + for(unsigned j = 0; j < dimension; j++) + if_matrix.cache.lines[i][j] = zone[i][j]; + for(i = 1; i < dimension; i++) + if_matrix.cache.lines[0][i] = IF_BOUND_INFTY; + + if (!if_normalize_zone(if_matrix.cache.lines)) + return if_empty_zone(); + + if_extrapolate_zone(if_matrix.cache.lines, if_matrix.extrapolation); + + for(i = 0; i < dimension; i++) + if_matrix.cache.matrix[i] = if_put_vector(if_matrix.cache.lines[i], dimension); + return if_put_matrix(if_matrix.cache.matrix, dimension); + +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_forward_zone(if_type_zone zone){ + unsigned dimension, forward = 1, i; + + if (if_is_empty_zone(zone)) + return zone; + + dimension = zone[0][0] + 1; + for(i = 1; i < dimension && forward; i++) + if (zone[i][0] < IF_BOUND_INFTY) + forward = 0; + if (forward) + return zone; + + for(i = 0; i < dimension; i++) + for(unsigned j = 0; j < dimension; j++) + if_matrix.cache.lines[i][j] = zone[i][j]; + for(i = 1; i < dimension; i++) + if_matrix.cache.lines[i][0] = IF_BOUND_INFTY; + + if (!if_normalize_zone(if_matrix.cache.lines)) + return if_empty_zone(); + + if_extrapolate_zone(if_matrix.cache.lines, if_matrix.extrapolation); + + for(i = 0; i < dimension; i++) + if_matrix.cache.matrix[i] = if_put_vector(if_matrix.cache.lines[i], dimension); + return if_put_matrix(if_matrix.cache.matrix, dimension); + +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_since_zone(if_type_zone zone, if_type_zone tpc){ + return if_close_zone + (if_intersect_zone + (tpc, if_forward_zone(if_intersect_zone(zone,tpc)))); +} + +/* +----------------------------------------------------------------------- +*/ + +if_type_zone if_diamond_zone(if_type_zone zone, int k){ + unsigned dimension, i; + + if (if_is_empty_zone(zone)) + return zone; + + if (k == 0) + return zone; + + dimension = zone[0][0] + 1; + for(i = 0; i < dimension; i++) + for(unsigned j = 0; j < dimension; j++) + if_matrix.cache.lines[i][j] = zone[i][j]; + for(i = 1; i < dimension; i++) + if (if_matrix.cache.lines[0][i] < IF_BOUND_INFTY) + if_matrix.cache.lines[0][i] += k; + + if (!if_normalize_zone(if_matrix.cache.lines)) + return if_empty_zone(); + + if_extrapolate_zone(if_matrix.cache.lines, if_matrix.extrapolation); + + for(i = 0; i < dimension; i++) + if_matrix.cache.matrix[i] = if_put_vector(if_matrix.cache.lines[i], dimension); + return if_put_matrix(if_matrix.cache.matrix, dimension); + +} + +/* +----------------------------------------------------------------------- +*/ + +int if_include_zone(if_type_zone zone1, if_type_zone zone2){ + unsigned dimension1, dimension2, i1, i2; + + if (if_is_empty_zone(zone1)) + return 1; + if (if_is_empty_zone(zone2)) + return 0; + + dimension1 = zone1[0][0] + 1; + dimension2 = zone2[0][0] + 1; + + if (dimension1 < dimension2) + return 0; + + for(i2 = 1, i1 = 1; i2 < dimension2; i2++, i1++) { + for(; i1 < dimension1 && zone1[i1][i1] < zone2[i2][i2]; i1++); + if (i1 == dimension1 || zone1[i1][i1] > zone2[i2][i2]) + return 0; + } + + for(i2 = 0, i1 = 0; i2 < dimension2; i2++, i1++){ + for(; i2 && i1 < dimension1 && zone1[i1][i1] < zone2[i2][i2]; i1++); + for(unsigned j2 = 0, j1 = 0; j2 < dimension2; j2++, j1++){ + for(; j2 && j1 < dimension1 && zone1[j1][j1] < zone2[j2][j2]; j1++); + if (i2 != j2 && zone1[i1][j1] > zone2[i2][j2]) + return 0; + } + } + + return 1; +} + +/* +----------------------------------------------------------------------- +*/ + +void if_print_matrix_zone(if_type_zone zone, FILE* file){ + fprintf(file,"\n"); + if (zone) + if_print_matrix(zone, zone[0][0] + 1, file); + else + fprintf(file, "[]\n"); +} + +void if_print_zone(if_type_zone zone, FILE* file){ + unsigned dimension, universal = 1; + + if (!zone) { + fprintf(file, " false"); + return; + } + + dimension = zone[0][0] + 1; + for(unsigned i = 0; i < dimension; i++) + for(unsigned j = 0; j < i; j++){ + unsigned rok = 0, lok = 0; + if (zone[i][j] < IF_BOUND_INFTY) + rok = 1; + if (zone[j][i] < IF_BOUND_INFTY) + lok = 1; + if (lok || rok) { + universal = 0; + fprintf(file, " c%d", zone[i][i]); + if (j) + fprintf(file, "-c%d", zone[j][j]); + fprintf(file, "="); + if (lok) + fprintf(file, "%s%d", if_sign_bound(zone[j][i]) ? "[" : "(", + -if_value_bound(zone[j][i])); + else + fprintf(file, "(_"); + fprintf(file, ","); + if (rok) + fprintf(file, "%d%s", if_value_bound(zone[i][j]), + if_sign_bound(zone[i][j]) ? "]" : ")"); + else + fprintf(file, "_)"); + } + } + + if (universal) + fprintf(file, " true"); + +} + +unsigned long if_hash_zone(if_type_zone zone, unsigned base) { + if (!zone) + return 0; + + return if_hash_matrix(zone, zone[0][0]+1, base); +} + + +/* +----------------------------------------------------------------------- +Zone Extrapolation +----------------------------------------------------------------------- +*/ + +void if_restrict_extrapolation_zone(if_type_zone zone){ + if_matrix.extrapolation = if_intersect_zone(if_matrix.extrapolation, zone); +} + + +void if_restrict_extrapolation_zone(int cmax){ + for(int i=0; i<64; i++) { + if_restrict_extrapolation_zone(if_clkle_zone(i,0,cmax)); + if_restrict_extrapolation_zone(if_clkge_zone(i,0,-cmax)); + } +} + + + + +/* +----------------------------------------------------------------------- +Time Progression +----------------------------------------------------------------------- +*/ + +void if_init_tpc(if_type_zone_list* tpclist){ + *tpclist = (if_type_zone_list) malloc(sizeof(struct if_struct_zone_list)); + (*tpclist)->zone = if_universal_zone(); + (*tpclist)->next = NULL; +} + +/* +----------------------------------------------------------------------- +*/ + +void if_clear_tpc(if_type_zone_list* tpclist) { + if_type_zone_list head, next; + + head = *tpclist; + while (head) { + next = head->next; + free(head); + head = next; + } + + *tpclist = NULL; +} + +/* +----------------------------------------------------------------------- +*/ + +void if_limit_tpc(if_type_zone_list* tpclist, if_type_zone base){ + if_type_zone_list zl = NULL, head, next; + if_type_zone z; + + head = *tpclist; + while (head != NULL) { + next = head->next; + z = if_intersect_zone(head->zone, base); + if (!if_is_empty_zone(z)) { + head->next = zl; + zl = head; + } + else + free(head); + head = next; + } + + *tpclist = zl; +} + +/* +----------------------------------------------------------------------- +*/ + +void if_restrict_tpc(if_type_zone_list* tpclist, if_type_zone tpc){ + if_type_zone_list zl = NULL, head, next; + if_type_zone z; + + head = *tpclist; + while (head != NULL) { + next = head->next; + z = if_intersect_zone(head->zone, tpc); + if (!if_is_empty_zone(z)) { + head->zone = z; + head->next = zl; + zl = head; + } + else + free(head); + head = next; + } + + *tpclist = zl; +} + +/* +----------------------------------------------------------------------- +*/ + +void if_create_restrict_tpc + (if_type_zone_list* tpclist, if_type_zone tpc, if_type_zone_list* tl){ + + for(if_type_zone_list head = *tpclist; head != NULL; head = head->next) { + if_type_zone z = if_intersect_zone(head->zone, tpc); + if (!if_is_empty_zone(z)) { + if_type_zone_list l = + (if_type_zone_list) malloc(sizeof(struct if_struct_zone_list)); + l->zone = z; + l->next = *tl; + *tl = l; + } + } + +} + +/* +----------------------------------------------------------------------- +*/ + +void if_guard_tpc(if_type_zone_list* tpclist, if_type_zone guard, int deadline){ + if_type_zone_list tl = NULL; + if_type_zone tpc; + unsigned dimension; + + if (if_is_empty_zone(guard)) + return; + + dimension = guard[0][0] + 1; + + if (deadline == 1) { // delayable + if_type_zone open_guard = if_open_zone(guard); + if (open_guard == guard) + // no tpc for right-open delayable guards + return; + + tpc = if_close_zone(if_backward_zone(guard)); + if_create_restrict_tpc(tpclist, tpc, &tl); + } + + if (deadline == 0 || deadline == 1){ // delayable or eager + unsigned universal = 1; + + for(unsigned i = 0; i < dimension && universal; i++) + for(unsigned j = 0; j < dimension && universal; j++) + if (i != j && guard[i][j] < IF_BOUND_INFTY) + universal = 0; + + if (!universal) { + for(unsigned i = 0; i < dimension; i++) + for(unsigned j = 0; j < dimension; j++) + if (i != j && guard[i][j] < IF_BOUND_INFTY && + (i == 0 || j == 0 || + guard[i][0] == IF_BOUND_INFTY || guard[0][j] == IF_BOUND_INFTY || + guard[i][j] < if_add_bound(guard[i][0], guard[0][j]))) { + if_type_zone neg_ij = if_clkcmp_zone(j ? guard[j][j] : 0, + i ? guard[i][i] : 0, + -if_value_bound(guard[i][j]), + !if_sign_bound(guard[i][j])); + tpc = if_close_zone(neg_ij); + if_create_restrict_tpc(tpclist, tpc, &tl); + } + } + + if_clear_tpc(tpclist); + *tpclist = tl; + } + +} + +/* +----------------------------------------------------------------------- +*/ + +void if_guard_split(if_type_zone_list* neglist, if_type_zone guard) +// builds the intersection of the negation of guards -> for priority-based state splits +{ + if_type_zone_list tl = NULL; + if_type_zone neg; + unsigned dimension; + unsigned universal = 1; + + if (if_is_empty_zone(guard)) + return; + if (*neglist == NULL) + return; + + dimension = guard[0][0] + 1; + + for(unsigned i = 0; i < dimension && universal; i++) + for(unsigned j = 0; j < dimension && universal; j++) + if (i != j && guard[i][j] < IF_BOUND_INFTY) + universal = 0; + if (universal) { + if_clear_tpc(neglist); + } else { + for(unsigned i = 0; i < dimension; i++) + for(unsigned j = 0; j < dimension; j++) + if (i != j && guard[i][j] < IF_BOUND_INFTY && + (i == 0 || j == 0 || + guard[i][0] == IF_BOUND_INFTY || guard[0][j] == IF_BOUND_INFTY || + guard[i][j] < if_add_bound(guard[i][0], guard[0][j]))) { + neg = if_clkcmp_zone(j ? guard[j][j] : 0, + i ? guard[i][i] : 0, + -if_value_bound(guard[i][j]), + !if_sign_bound(guard[i][j])); + if_create_restrict_tpc(neglist, neg, &tl); + } + if_clear_tpc(neglist); + *neglist = tl; + } + +} + +/* +----------------------------------------------------------------------- +*/ + +int if_simple_is_universal_zone_list(if_type_zone_list neglist) +{ + return neglist != NULL && neglist->next==NULL && neglist->zone == if_universal_zone(); +} + +/* +----------------------------------------------------------------------- +Init / Exit Zone Module +----------------------------------------------------------------------- +*/ + +void if_init_zone_module() { + if_init_vector_table(); + if_init_matrix_table(); +} + +void if_exit_zone_module() { + // if_info_matrix_table(stdout); + if_exit_matrix_table(); + // if_info_vector_table(stdout); + if_exit_vector_table(); +} + +/* +----------------------------------------------------------------------- +*/ + diff --git a/src/simulator/ifzone.h b/src/simulator/ifzone.h new file mode 100644 index 0000000000000000000000000000000000000000..6e20e87a971b54a82f1e74c87fa80d6295d93812 --- /dev/null +++ b/src/simulator/ifzone.h @@ -0,0 +1,314 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * Zone / Clock DBM Interface + * + */ + +#ifndef IFZONE_H +#define IFZONE_H + + + +/* +----------------------------------------------------------------------- +Bound Definition +----------------------------------------------------------------------- +*/ + +#define IF_SIGN_LE \ + (1) + +#define IF_SIGN_LT \ + (0) + + +typedef int if_type_bound; + +#define if_make_bound(value,sign) \ + (((value) << 1) | (sign)) + +#define if_value_bound(bound) \ + ((bound) >> 1) + +#define if_sign_bound(bound) \ + ((bound) & 1) + +#define if_complement_bound(bound) \ + if_make_bound(-if_value_bound((bound)),!if_sign_bound((bound))) + +#define if_min_bound(bound1,bound2) \ + ((bound1) < (bound2) ? (bound1) : (bound2)) + +#define if_add_bound(bound1,bound2) \ + ((((bound1) & ~1) + ((bound2) & ~1)) | ((bound1) & (bound2) & 1)) + +void if_print_bound(if_type_bound, FILE*); + +#define IF_BOUND_INFTY \ + (0x10000000) + + + + +/* +----------------------------------------------------------------------- +Vector / Vector Table Definition +----------------------------------------------------------------------- +*/ + +typedef if_type_bound* if_type_vector; + +typedef struct if_struct_vector_list { + if_type_vector vector; + struct if_struct_vector_list * next; +} * if_type_vector_list; + +/* * */ + +if_type_vector if_create_vector(unsigned); + +if_type_vector if_duplicate_vector(if_type_vector, unsigned); + +void if_delete_vector(if_type_vector, unsigned); + +void if_copy_vector(if_type_vector, if_type_vector, unsigned); + +int if_compare_vector(if_type_vector, if_type_vector, unsigned); + +unsigned long if_hash_vector(if_type_vector, unsigned, unsigned); + +void if_print_vector(if_type_vector, unsigned, FILE*); + +/* * */ + +void if_init_vector_table(); + +void if_exit_vector_table(); + +void if_info_vector_table(FILE*); + +if_type_vector if_put_vector(if_type_vector, unsigned); + + + + +/* +----------------------------------------------------------------------- +Matrix / Matrix Table Definition +----------------------------------------------------------------------- +*/ + +typedef if_type_vector* if_type_matrix; + +typedef struct if_struct_matrix_list { + if_type_matrix matrix; + struct if_struct_matrix_list * next; +} * if_type_matrix_list; + +/* * */ + +if_type_matrix if_create_matrix(unsigned); + +void if_delete_matrix(if_type_matrix, unsigned); + +void if_copy_matrix(if_type_matrix, if_type_matrix, unsigned); + +int if_compare_matrix(if_type_matrix, if_type_matrix, unsigned); + +unsigned long if_hash_matrix(if_type_matrix, unsigned, unsigned); + +void if_print_matrix(if_type_matrix, unsigned, FILE*); + +/* * */ + +void if_init_matrix_table(); + +void if_exit_matrix_table(); + +void if_info_matrix_table(FILE*); + +if_type_matrix if_put_matrix(if_type_matrix, unsigned); + + + + +/* +----------------------------------------------------------------------- +Zone Definition +----------------------------------------------------------------------- +*/ + +typedef if_type_matrix if_type_zone; + +typedef struct if_struct_zone_list { + if_type_zone zone; + struct if_struct_zone_list * next; +} * if_type_zone_list; + + +#define if_copy_zone(dst,src) \ + (dst)=(src) + +#define if_compare_zone(zone1,zone2) \ + ((zone1)!=(zone2)) + + +if_type_zone if_empty_zone(); + +if_type_zone if_universal_zone(); + + + +int if_is_empty_zone(if_type_zone); + +int if_is_universal_zone(if_type_zone zone); + +int if_clock_in_zone(if_type_zone, int); + + +if_type_zone if_clkcmp_zone(int, int, int, int); + +if_type_zone if_clklt_zone(int, int, int); + +if_type_zone if_clkle_zone(int, int, int); + +if_type_zone if_clkge_zone(int, int, int); + +if_type_zone if_clkgt_zone(int, int, int); + +if_type_zone if_clkeq_zone(int, int, int); + + +int if_normalize_zone(if_type_zone); /* internal use only */ + +int if_extrapolate_zone(if_type_zone); /* internal use only */ + + +if_type_zone if_intersect_zone(if_type_zone, if_type_zone); + +if_type_zone if_exists_zone(if_type_zone, int); + +if_type_zone if_set_zone(if_type_zone, int, int); + + +if_type_zone if_round_zone(if_type_zone, int, int); + +if_type_zone if_open_right_zone(if_type_zone); + +if_type_zone if_close_right_zone(if_type_zone); + +if_type_zone if_open_left_zone(if_type_zone); + +if_type_zone if_close_left_zone(if_type_zone); + +if_type_zone if_open_zone(if_type_zone); + +if_type_zone if_close_zone(if_type_zone); + + +if_type_zone if_backward_zone(if_type_zone); + +if_type_zone if_forward_zone(if_type_zone); + + +if_type_zone if_since_zone(if_type_zone, if_type_zone); + + +if_type_zone if_diamond_zone(if_type_zone, int); + + +int if_include_zone(if_type_zone, if_type_zone); + + +void if_print_zone(if_type_zone, FILE*); + +unsigned long if_hash_zone(if_type_zone, unsigned); + + + +/* +----------------------------------------------------------------------- +Zone Extrapolation +----------------------------------------------------------------------- +*/ + +void if_restrict_extrapolation_zone(if_type_zone); + +void if_restrict_extrapolation_zone(int); + + + +/* +----------------------------------------------------------------------- +Time Progression +----------------------------------------------------------------------- +*/ + +void if_init_tpc(if_type_zone_list*); + +void if_clear_tpc(if_type_zone_list*); + + +void if_limit_tpc(if_type_zone_list*, if_type_zone); + +void if_restrict_tpc(if_type_zone_list*, if_type_zone); + +void if_guard_tpc(if_type_zone_list*, if_type_zone, int); + +void if_guard_split(if_type_zone_list*, if_type_zone); // builds the intersection of the negation of guards -> for priority-based state splits + + +int if_simple_is_universal_zone_list(if_type_zone_list); + + +/* +----------------------------------------------------------------------- +Init / Exit Zone Module +----------------------------------------------------------------------- +*/ + +void if_init_zone_module(); + +void if_exit_zone_module(); + +#endif diff --git a/src/simulator/instance.C b/src/simulator/instance.C new file mode 100644 index 0000000000000000000000000000000000000000..d33ac4b0d4af3007976216afaa87d504a1d7d7e1 --- /dev/null +++ b/src/simulator/instance.C @@ -0,0 +1,126 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * instance : implements abstract process instances + * + */ + +IfIterator* IfInstance::ITERATOR = NULL; + +const char* IfInstance::PROCNAME[PROCMAXNUM] = {"nil"}; + +unsigned IfInstance::STATUS = 0; + +unsigned IfInstance::STEP = 0; + +IfInstance::IfInstance(if_pid_type pid, IfQueue* queue) + : IfObject() { + m_pid = pid; + m_queue = queue; +} + +IfInstance::IfInstance(const IfInstance& instance) + : IfObject(instance) { + m_pid = instance.m_pid; + m_queue = instance.m_queue; +} + +IfInstance::~IfInstance() { +} + +void IfInstance::deliver(const IfMessage* message) { + m_queue = (IfQueue*) m_queue->putTail(message->store()); +} + +void IfInstance::RemoveFromQueue(const IfMessage* message) { + m_queue = (IfQueue*) m_queue->remove(message); +} + +void IfInstance::copy(const IfInstance* instance) { + m_pid = instance->m_pid; + m_queue = instance->m_queue; +} + +void IfInstance::iterate(IfIterator*) { + // abstract +} + +void IfInstance::reset() { + // abstract +} + + +int IfInstance::compare(const IfInstance* instance) const { + int cmp = 0; + if (cmp == 0) cmp = (long) m_pid - (long) instance->m_pid; + if (cmp == 0) cmp = (long) m_queue - (long) instance->m_queue; + return cmp; +} + +long unsigned IfInstance::hash(const unsigned long base) const { + return ((m_pid + ((unsigned long) m_queue)) >> 4) % base; +} + +IfInstance* IfInstance::copy() const { + return new IfInstance(*this); +} + +void IfInstance::print(FILE* file) const { + if_pid_print(m_pid,file); + fprintf(file, "\t\t{"); + m_queue->print(file); + fprintf(file, "}"); +} + +void IfInstance::printXML(std::ostream& buf) const { + buf << "<self>\n"; + if_pid_print_xml(m_pid,buf); + buf << "</self>\n"; + buf << "<queue>\n"; + m_queue->printXML(buf); + buf << "</queue>\n"; +} + +IMPLEMENT_STORE(IfInstance,"instance") + diff --git a/src/simulator/instance.h b/src/simulator/instance.h new file mode 100644 index 0000000000000000000000000000000000000000..070f3ad520ada5c896a954d58b33b012f85dba7b --- /dev/null +++ b/src/simulator/instance.h @@ -0,0 +1,122 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * instance : defines abstract process instances + * + */ + +#define PROCMAXNUM 1024 + +class IfInstance : public IfObject { + + public: + IfInstance(if_pid_type = 0, IfQueue* = IfQueue::NIL); + IfInstance(const IfInstance&); + virtual ~IfInstance(); + + public: + inline if_pid_type getPid() const + { return m_pid; } + inline void setPid(if_pid_type pid) + { m_pid = pid;} + + public: + virtual int getPriority() const + { return 0; } + virtual void deliver(const IfMessage*); + inline IfQueue* GetQueue() const { return m_queue; } + virtual void RemoveFromQueue(const IfMessage*); + + public: + virtual int isObsSuccess() const { return 0; } + virtual int isObsError() const { return 0; } + virtual int isCut() const { return 0; } + + public: + virtual void copy(const IfInstance*); + virtual void iterate(IfIterator*); + virtual void reset(); + + public: + DECLARE_STORABLE(IfInstance) + DECLARE_STORE(IfInstance) + + public: + enum { CREATE = 1 }; + + public: + static IfIterator* ITERATOR; + static const char* PROCNAME[PROCMAXNUM]; + static unsigned STATUS; + static unsigned STEP; + + protected: + if_pid_type m_pid; + IfQueue* m_queue; + +}; + + +/* + * + * state : defines abstract state informations + * + */ + +enum { + UNSTABLE = 1, // the state is unstable + TSIG = 2, // signal-triggered transitions + TNONE = 4, // none-triggered transitions + OSUCCESS = 8, // observer success state + OERROR = 16, // observer success state + CONTROL = 64 // the top state of a parallel region +}; + +template <unsigned L, typename T> +struct if_state { + const char* name; // state name + unsigned parent; // parent state + unsigned entry; // entry state + unsigned flags; // stable, queue, none, success, error + char sigtab[L]; // saved, input + T dispatch; // message dispatcher +}; diff --git a/src/simulator/iterator.C b/src/simulator/iterator.C new file mode 100644 index 0000000000000000000000000000000000000000..7f0ca7e91b1f71947b2203cfb8a25e3c6de4f0d0 --- /dev/null +++ b/src/simulator/iterator.C @@ -0,0 +1,774 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * abstract handler implementation + * + */ + +IfHandler::IfHandler() { + m_flags = 0; + m_version = 0; +} + +IfHandler::IfHandler(const IfHandler& handler) { + m_flags = handler.m_flags; + m_version = handler.m_version; +} + +IfHandler::~IfHandler() { +} + +void IfHandler::record() { + // abstract +} + +void IfHandler::restore() { + // abstract +} + +void IfHandler::forget() { + // abstract +} + +void IfHandler::print(FILE* file) const { + fprintf(file, "\n%c%c%c%c %2d ", + testFlag(MOVED) ? 'M' : '-', + testFlag(DEAD) ? 'D' : '-', + testFlag(TIME) ? 'T' : '-', + testFlag(VISIBLE) ? 'O' : '-', + m_version); +} + +/* + * + * label handler : implements running trace handler + * + */ + +IfLabelHandler::IfLabelHandler() + : IfHandler(), m_label(LABELMAXSIZE) { + m_length = 0; + for(int i = 0; i < LABELMAXSIZE; i++) { + m_label.setAt(i, NULL); + m_tab[i] = 0; + } +} + +IfLabelHandler::~IfLabelHandler() { +} + +int IfLabelHandler::trace(const IfEvent* event) { + int ok = 1; + if (m_length < LABELMAXSIZE - 1) { + m_label.setAt(m_length, event); + m_tab[m_length] = m_version; + m_length++; + } + else { + // truncate + ok = 0; + } + return ok; +} + +void IfLabelHandler::record() { + m_version++; +} + +void IfLabelHandler::restore() { + while (m_length && m_tab[m_length - 1] == m_version) { + m_label.setAt(m_length - 1, NULL); + m_tab[m_length - 1] = 0; + m_length--; + } +} + +void IfLabelHandler::forget() { + restore(); + m_version--; +} + +void IfLabelHandler::print(FILE* file) const { + IfHandler::print(file); + m_label.print(file); +} + +/* + * + * instance handler : implements running instance handler + * + */ + +IfInstanceHandler::IfInstanceHandler(IfInstance* instance) + : IfHandler() { + m_current = instance->copy(); + m_store = instance; + m_prev = NULL; +} + +IfInstanceHandler::IfInstanceHandler(const IfInstanceHandler& handler) + : IfHandler(handler) { + m_current = handler.m_current->copy(); + m_store = handler.m_store; + m_prev = handler.m_prev; +} + +IfInstanceHandler::~IfInstanceHandler() { + if (m_current) delete m_current; +} + +void IfInstanceHandler::record() { + m_prev = new IfInstanceHandler(*this); + // warning : the version number is not set here +} + +void IfInstanceHandler::restore() { + m_flags = m_prev->m_flags; + m_current->copy(m_prev->m_current); + m_store = m_prev->m_store; +} + +void IfInstanceHandler::forget() { + IfInstanceHandler* prev = m_prev; + restore(); + m_version = m_prev->m_version; + m_prev = m_prev->m_prev; + delete prev; +} + +void IfInstanceHandler::print(FILE* file) const { + IfHandler::print(file); + m_current->print(file); +} + +/* + * + * config handler : implements running configuration handler + * + */ + +IfConfigHandler::IfConfigHandler() + : IfHandler() { + m_running = NULL; +} + +IfConfigHandler::~IfConfigHandler() { +} + +int IfConfigHandler::deliver(const if_pid_type pid, + const IfMessage* message) { + Node* node = retrieve(pid); + + if (node) { + m_instances.getAt(node)->deliver(message); + m_instances.getAt(node)->setFlag(MOVED); + } + + return node ? 1 : 0; +} + +int IfConfigHandler::fork(IfInstance* instance, + if_pid_type* pid) { + Node* node = NULL; + IfInstanceHandler* handler = NULL; + + *pid = instance->getPid() & PROCMASK; + + for(node = m_instances.getFirst(); node != NULL; + node = m_instances.getNext(node)) { + handler = m_instances.getAt(node); + + if (handler->getPid() < *pid) + continue; + if (handler->getPid() == *pid) { + if (!handler->testFlag(DEAD)) + (*pid)++; + continue; + } + if (handler->getPid() > *pid) + break; + } + + instance->setPid(*pid); + + handler = new IfInstanceHandler(instance->store()); + handler->setVersion(m_version); + + if (node) + m_instances.insert(handler, node); + else + m_instances.append(handler); + + return 1; +} + +int IfConfigHandler::kill(const if_pid_type pid) { + Node* node = retrieve(pid); + + if (node) { + m_instances.getAt(node)->kill(); + m_instances.getAt(node)->setFlag(DEAD); + } + + return node ? 1 : 0; +} + +int IfConfigHandler::trace(const IfEvent* event) { + + // filter uninteresting events + if(m_running->getCurrent()->getPriority() == OBSERVER_PRIORITY) + return 1; + switch(event->getKind()) { + case IfEvent::INFORMAL: + case IfEvent::INPUT: + case IfEvent::DISCARD: + case IfEvent::OUTPUT: + case IfEvent::FORK: + case IfEvent::KILL: + case IfEvent::DELIVER: + case IfEvent::PROBABILITY: + break; + default: return 1; + } + + Node* node = NULL; + IfInstanceHandler* handler = NULL; + event = event->store(); + + for(node = m_instances.getFirst(); node != NULL; + node = m_instances.getNext(node)) { + handler = m_instances.getAt(node); + + if (handler->getPriority() == OBSERVER_PRIORITY) { + if (handler->getVersion() < m_version) { + handler->record(); + handler->setVersion(m_version); + } + + ((IfObserverInstance*)handler->getCurrent())->trace(event); + handler->setFlag(MOVED); + } + } + + return 1; +} + +int IfConfigHandler::guard(IfTime::Constraint* constraints, + const if_deadline deadline) { + Node* node = retrieveTime(); + int enabled = 0; + + if (node) { + enabled = m_instances.getAt(node)->guard(constraints, deadline); + m_instances.getAt(node)->setFlag(MOVED); + } + + return enabled; +} + +int IfConfigHandler::set(if_clock_type* clock, + const if_time_value value, + const if_pid_type pid) { + Node* node = retrieveTime(); + + if (node) { + m_instances.getAt(node)->set(clock, value, pid); + m_instances.getAt(node)->setFlag(MOVED); + } + + return node ? 1 : 0; +} + +int IfConfigHandler::reset(if_clock_type* clock) { + Node* node = retrieveTime(); + + if (node) { + m_instances.getAt(node)->reset(clock); + m_instances.getAt(node)->setFlag(MOVED); + } + + return node ? 1 : 0; +} + +int IfConfigHandler::active(const if_clock_type clock) { + Node* node = retrieveTime(); + + return node ? m_instances.getAt(node)->active(clock) : 0; +} + +int IfConfigHandler::timeval(const if_clock_type clock) { + Node* node = retrieveTime(); + + return node ? m_instances.getAt(node)->timeval(clock) : -1; +} + +int IfConfigHandler::acquire(const if_pid_type locker, + const int* resources) { + Node* node = retrieveMonitor(); + int available = 0; + + if (node) { + available = m_instances.getAt(node)->acquire(locker, resources); + m_instances.getAt(node)->setFlag(MOVED); + } + + return available; +} + +int IfConfigHandler::release(const if_pid_type locker, + const int* resources) { + Node* node = retrieveMonitor(); + + if (node) { + m_instances.getAt(node)->release(locker, resources); + m_instances.getAt(node)->setFlag(MOVED); + } + + return 1; +} + +IfInstance* IfConfigHandler::import(const if_pid_type pid) { + Node* node = retrieve(pid); + + if (node == NULL) { + // unrecoverable simulation error: + // [direct] instance adressing fault + fprintf(stderr, "\nerror #1: instance addressing fault!\n"); + if_pid_print(pid, stderr); +throw IfDynamicError(IfDynamicError::IAF); +// exit(1); + } + + m_instances.getAt(node)->setFlag(MOVED); + + return m_instances.getAt(node)->getCurrent(); +} + +int IfConfigHandler::fetchPid(const if_pid_type proc) { + Node* node = NULL; + IfInstanceHandler* handler = NULL; + if_pid_type pid = 0; + int n = 0; + + for(node = m_instances.getFirst(); node != NULL; + node = m_instances.getNext(node)) { + handler = m_instances.getAt(node); + pid = handler->getPid(); + + if ((pid & PROCMASK) == proc) { + assert(n < PIDTMAXSIZE-1); + m_pidt[n++] = pid; + } + else if ((pid & PROCMASK) > proc) + break; + } + + return n; +} + +void IfConfigHandler::put(const IfConfig* source) { + IfConfig::Chunk* chunk = NULL; + IfInstance* instance = NULL; + + m_instances.purge(); + + for(int i = 0; (chunk = source->getAt(i)); i++) + for(int j = 0; j < CONFIGCHUNKSIZE && + (instance = chunk->getAt(j)); j++) + m_instances.append(new IfInstanceHandler(instance)); +} + +IfConfig* IfConfigHandler::get() const { + Node* node = NULL; + IfInstanceHandler* handler = NULL; + + IfConfig target(CONFIGMAXSIZE); + IfConfig::Chunk chunk; + int i = 0, j = 0; + + for(node = m_instances.getFirst(); node != NULL; + node = m_instances.getNext(node)) { + handler = m_instances.getAt(node); + + if (handler->testFlag(DEAD)) + continue; + if (handler->testFlag(MOVED)) { + handler->store(); + handler->resetFlag(MOVED); + } + chunk.setAt(j++, handler->getStore()); + if (j == CONFIGCHUNKSIZE) { + if (i < CONFIGMAXSIZE) + target.setAt(i++, chunk.store()); + j = 0; + } + } + if (j != 0) { + for(; j < CONFIGCHUNKSIZE;) + chunk.setAt(j++, NULL); + if (i < CONFIGMAXSIZE) + target.setAt(i++, chunk.store()); + } + if (i < CONFIGMAXSIZE) + target.setAt(i++, NULL); + if (i >= CONFIGMAXSIZE) { + // unrecoverable simulation error: + // [direct] configuration size exceeds pre-allocated buffer + fprintf(stderr, "\nerror #2: configuration overflow!\n"); + exit(1); + } + + if (m_running) // is null in start() + m_running->setFlag(MOVED); + + return target.store(); +} + +void IfConfigHandler::iterate(IfIterator* iter) { + Node* node = NULL; + int last_level = OBSERVER_PRIORITY; + + for(node = m_instances.getFirst(); node != NULL; + node = m_instances.getNext(node)) + m_heap.put(m_instances.getAt(node)); + + while ((m_running = m_heap.get()) != NULL) { + /*!!!*/ + if(opt_use_priorities && m_running->getPriority() < last_level) { + last_level = m_running->getPriority(); + if(m_running->getPriority() > -1) { + Node* node = retrieveTime(); + + if (node) { + IfInstanceHandler* tmp = m_running; + + m_running = m_instances.getAt(node); + iter->setPriority(OBSERVER_PRIORITY); // split has maximal priority + m_running->setFlag(MOVED); + iter->record(); + + for(node = m_instances.getFirst(); node != NULL; node = m_instances.getNext(node)) + if(m_instances.getAt(node)->getPriority() == OBSERVER_PRIORITY) { + ((IfObserverInstance*)m_instances.getAt(node)->getCurrent())->flushLabel(); + m_instances.getAt(node)->setFlag(MOVED); + } + + m_running->splitByPrio(iter); + + iter->forget(); + m_running->resetFlag(MOVED); + + m_running = tmp; + } + } + } + + iter->setPriority(m_running->getPriority()); + m_running->setFlag(MOVED); + iter->record(); + + if(opt_use_priorities && m_running->getPriority() < OBSERVER_PRIORITY) + for(node = m_instances.getFirst(); node != NULL; node = m_instances.getNext(node)) + if(m_instances.getAt(node)->getPriority() == OBSERVER_PRIORITY) { + ((IfObserverInstance*)m_instances.getAt(node)->getCurrent())->flushLabel(); + m_instances.getAt(node)->setFlag(MOVED); + } + + m_running->iterate(iter); + iter->forget(); + m_running->resetFlag(MOVED); + } +} + +void IfConfigHandler::record() { + m_version++; + m_running->record(); + m_running->setVersion(m_version); +} + +void IfConfigHandler::restore() { + Node *node = NULL, *next = NULL; + IfInstanceHandler* handler = NULL; + + for(node = m_instances.getFirst(); node != NULL; + node = next) { + next = m_instances.getNext(node); + handler = m_instances.getAt(node); + + if (handler->getVersion() == m_version) { + if (handler->getPrev()) // some previous level recorded + handler->restore(); + else // just created at current record level + m_instances.remove(node); + } + } +} + +void IfConfigHandler::forget() { + Node *node = NULL, *next = NULL; + IfInstanceHandler* handler = NULL; + + for(node = m_instances.getFirst(); node != NULL; + node = next) { + next = m_instances.getNext(node); + handler = m_instances.getAt(node); + + if (handler->getVersion() == m_version) { + if (handler->getPrev()) // some previous level recorded + handler->forget(); + else // just created at current record level + m_instances.remove(node); + } + } + + m_version--; +} + +IfConfigHandler::Node* IfConfigHandler::retrieve(const if_pid_type pid) { + Node* node = NULL; + IfInstanceHandler* handler = NULL; + + for(node = m_instances.getFirst(); node != NULL; + node = m_instances.getNext(node)) { + handler = m_instances.getAt(node); + + if (handler->getPid() == pid && + !handler->testFlag(DEAD)) + break; + if (handler->getPid() > pid) { + node = NULL; + handler = NULL; + break; + } + } + + if (handler && + handler->getVersion() < m_version) { + handler->record(); + handler->setVersion(m_version); + } + + return node; +} + +IfConfigHandler::Node* IfConfigHandler::retrieveTime() { + Node* node = m_instances.getLast(); + IfInstanceHandler* handler = m_instances.getAt(node); + + if (handler && + handler->getVersion() < m_version) { + handler->record(); + handler->setVersion(m_version); + } + + return node; +} + +IfConfigHandler::Node* IfConfigHandler::retrieveMonitor() { + Node* last = m_instances.getLast(); + Node* node = m_instances.getPrev(last); + IfInstanceHandler* handler = m_instances.getAt(node); + + if (handler && + handler->getVersion() < m_version) { + handler->record(); + handler->setVersion(m_version); + } + + return node; +} + +void IfConfigHandler::print(FILE* file) const { + Node* node = NULL; + IfInstanceHandler* handler = NULL; + + IfHandler::print(file); + + for(node = m_instances.getFirst(); node != NULL; + node = m_instances.getNext(node)) { + handler = m_instances.getAt(node); + handler->print(file); + } +} + +/* + * + * iter : implements iteration loop on configurations + * + */ + +IfIterator::IfIterator() + : IfEngine() { + m_source = NULL; + m_nCutFlags = 0; +} + +IfIterator::IfIterator(const IfDriver* driver) + : IfEngine(driver) { + m_source = NULL; +} + +IfIterator::~IfIterator() { +} + +void IfIterator::record() { + m_config.record(); + m_label.record(); +} + +void IfIterator::restore() { + m_config.restore(); + m_label.restore(); +} + +void IfIterator::forget() { + m_config.forget(); + m_label.forget(); +} + +void IfIterator::print(FILE* file) const { + m_config.print(file); + m_label.print(file); +} + +void IfIterator::run(const IfConfig* source) { + if( (m_nCutFlags & ON_ERROR) && source->isObsError() ) + return; + if( (m_nCutFlags & ON_SUCCESS) && source->isObsSuccess() ) + return; + if( source->isCut() ) + return; + m_source = (IfConfig*) source; + m_config.put(m_source); + + m_complete = -1; + m_config.iterate(this); +} + +void IfIterator::step() { + if (m_label.getLength() == 0) + trace(IfEvent::SKIP, m_config.getRunning()->getPid(), ""); + + if (m_complete == -1) + m_complete = m_priority; + if (m_priority == m_complete || + (m_priority == -1 /* time */ && m_complete != OBSERVER_PRIORITY)) + m_driver->explore(m_source, m_label.getLabel(), m_config.get()); + + IfInstance::STEP++; +} + +/* + * + * 2HopsIterator : interface of iteration loop on configurations + * drives another Engine, and returns a (discrete) successor only if in the source state + * there is no "tick" transition or there is only a self "tick" + * + */ + +If2HopsEngine::If2HopsEngine() + : IfEngine(), IfDriver() +{ + m_lSuccessors = NULL; +} + +If2HopsEngine::If2HopsEngine(const IfEngine* engine, const IfDriver* driver) + : IfEngine(driver), IfDriver(engine) +{ + m_lSuccessors = NULL; +} + +If2HopsEngine::~If2HopsEngine() +{ +} + +IfConfig* If2HopsEngine::start() +{ + return m_engine->start(); +} + +void If2HopsEngine::run(const IfConfig* source) +{ + if(m_lSuccessors) delete m_lSuccessors; + m_lSuccessors = NULL; + + m_engine->run(source); + + // tests whether there are TIKC successors that are not self + int explSucc = 1; + Successor* tmp = m_lSuccessors; + while(tmp) { + if(tmp->label->getLength() && + (tmp->label->getAt(0)->getKind() == IfEvent::TICK) && + strcmp(tmp->label->getAt(0)->getValue(), "split") && + source->compare(tmp->state) ) // it's a TICK, but not a self TICK + { + explSucc = 0; + break; + } + + tmp = tmp->next; + } + + // explore discrete successors only if explSucc + tmp = m_lSuccessors; + while(tmp) { + if(explSucc) { + m_driver->explore((IfConfig*)source, tmp->label, tmp->state); + } else { + if(tmp->label->getLength() && (tmp->label->getAt(0)->getKind() == IfEvent::TICK) ) + m_driver->explore((IfConfig*)source, tmp->label, tmp->state); + } + if(tmp->label) delete tmp->label; + + tmp = tmp->next; + } +} + +void If2HopsEngine::explore(IfConfig* source, + IfLabel* label, + IfConfig* target) +{ + m_lSuccessors = new Successor(target, label?label->copy():NULL, m_lSuccessors); +} diff --git a/src/simulator/iterator.h b/src/simulator/iterator.h new file mode 100644 index 0000000000000000000000000000000000000000..cdb14e38189a53b3c26d2fba2302e6864278ff9c --- /dev/null +++ b/src/simulator/iterator.h @@ -0,0 +1,424 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * abstract handler interface + * + */ + +class IfHandler { + + public: + enum Flag { + MOVED = 1, // stored version != current version + DEAD = 2, // the current instance was killed + VISIBLE = 4, // the instance does some visible actions + TIME = 8 // the discrete / continuous time + }; + + public: + IfHandler(); + IfHandler(const IfHandler&); + virtual ~IfHandler(); + + public: + inline int testFlag(const unsigned flag) const + { return m_flags & flag; } + inline void setFlag(const unsigned flag) + { m_flags |= flag; } + inline void resetFlag(const unsigned flag) + { m_flags &= (~flag); } + + public: + inline unsigned getVersion() const + { return m_version; } + inline void setVersion(const unsigned version) + { m_version = version; } + + public: + DECLARE_RECORDABLE(IfHandler) + + protected: + unsigned m_flags; + unsigned m_version; + +}; + +/* + * + * label handler : defines label handler + * + */ + +#define LABELMAXSIZE 16384 + +class IfLabelHandler : public IfHandler { + + public: + IfLabelHandler(); + virtual ~IfLabelHandler(); + + public: + inline IfLabel* getLabel() const + { return (IfLabel*) &m_label; } + inline int getLength() const + { return m_length; } + + public: + int trace(const IfEvent*); + + public: + DECLARE_RECORDABLE(IfLabelHandler) + + protected: + IfLabel m_label; // traced label + unsigned m_length; // traced label length + unsigned m_tab[LABELMAXSIZE]; // event level table + +}; + +/* + * + * instance handler : defines instance handler + * + */ + +class IfInstanceHandler : public IfHandler { + + public: + IfInstanceHandler(IfInstance*); + IfInstanceHandler(const IfInstanceHandler&); + virtual ~IfInstanceHandler(); + + public: + inline IfInstance* getCurrent() const + { return m_current; } + inline IfInstance* getStore() const + { return m_store; } + inline IfInstanceHandler* getPrev() const + { return m_prev; } + + inline if_pid_type getPid() const + { return m_current->getPid(); } + inline int getPriority() const + { return m_current->getPriority(); } + + public: + inline void store() + { m_store = m_current->store(); } + + inline void deliver(const IfMessage* message) + { m_current->deliver(message); } + inline void kill() + { m_current->reset(); } + inline void iterate(IfIterator* iterator) + { m_current->iterate(iterator); } + inline void splitByPrio(IfIterator* iterator) + { ((IfTime*) m_current)->splitByPrio(iterator); } + + public: + inline int guard(IfTime::Constraint* constraints, + const if_deadline deadline) + { return ((IfTime*) m_current)->guard(constraints, deadline); } + inline void set(if_clock_type* clock, + const if_time_value value, + const if_pid_type pid) + { ((IfTime*) m_current)->set(clock, value, pid); } + inline void reset(if_clock_type* clock) + { ((IfTime*) m_current)->resetClock(clock); } + inline int active(const if_clock_type clock) + { return ((IfTime*) m_current)->active(clock); } + inline int timeval(const if_clock_type clock) + { return ((IfTime*) m_current)->timeval(clock); } + + public: + inline int acquire(const if_pid_type locker, + const int* resources) + { return ((IfMonitor*) m_current)->acquire(locker, resources); } + inline int release(const if_pid_type locker, + const int* resources) + { return ((IfMonitor*) m_current)->release(locker, resources); } + + public: + DECLARE_RECORDABLE(IfInstanceHandler) + + protected: + IfInstance* m_current; // current instance + IfInstance* m_store; // last stored version + IfInstanceHandler* m_prev; // record list + +}; + +/* + * + * config handler : defines configuration handler + * + */ + +#define CONFIGMAXSIZE 4096 + /* in Chunks, up to 6000 instances */ +#define PIDTMAXSIZE 8192 + // enough ?? + +class IfConfigHandler : public IfHandler { + + public: + IfConfigHandler(); + virtual ~IfConfigHandler(); + + public: + int deliver(const if_pid_type, + const IfMessage*); + int fork(IfInstance*, + if_pid_type*); + int kill(const if_pid_type); + int trace(const IfEvent* event); + + public: + int guard(IfTime::Constraint*, + const if_deadline); + int set(if_clock_type*, + const if_time_value, + const if_pid_type); + int reset(if_clock_type*); + int active(const if_clock_type); + int timeval(const if_clock_type); + + public: + int acquire(const if_pid_type, + const int*); + int release(const if_pid_type, + const int*); + + public: + IfInstance* import(const if_pid_type); + + public: + inline if_pid_type getPid(const int i) const + { return m_pidt[i]; } + int fetchPid(const if_pid_type); + + public: + inline IfInstanceHandler* getRunning() const + { return m_running; } + + public: + void put(const IfConfig*); + IfConfig* get() const; + + public: + void iterate(IfIterator*); + + public: + DECLARE_RECORDABLE(IfConfigHandler) + + protected: + typedef IfLinkedList<IfInstanceHandler>::Node Node; + + protected: + Node* retrieve(const if_pid_type); + Node* retrieveTime(); + Node* retrieveMonitor(); + + protected: + IfLinkedList<IfInstanceHandler> m_instances; + + IfHeap<IfInstanceHandler> m_heap; + IfInstanceHandler* m_running; + + if_pid_type m_pidt[PIDTMAXSIZE]; + +}; + +/* + * + * iterator : interface of iteration loop on configurations + * + */ + + +class IfIterator : public IfEngine { + + public: + enum ECutFlags { + ON_ERROR = 1, + ON_SUCCESS = 2, + }; + + public: + IfIterator(); + IfIterator(const IfDriver* driver); + virtual ~IfIterator(); + + public: + inline int trace(const IfEvent* event) + { + m_config.trace(event); + return m_label.trace(event); + } + inline int trace(const IfEvent::Kind kind, + const if_pid_type pid, + const char* value, + const if_pid_type auxPid = 0, + IfObject* auxObj = NULL) + { IfEvent* event = new IfEvent(kind, pid, value, auxPid, auxObj); + return trace(event); } + inline int trace(const IfEvent::Kind kind, + const if_pid_type pid, + const char* value, + const double proba) + { IfEvent* event = new IfEvent(kind, pid, value, proba); + return trace(event); } + + public: + inline int deliver(const if_pid_type pid, + const IfMessage* message) + { return m_config.deliver(pid, message); } + inline int fork(IfInstance* instance, + if_pid_type* pid) + { return m_config.fork(instance, pid); } + inline int kill(const if_pid_type pid) + { return m_config.kill(pid); } + + public: + inline int guard(IfTime::Constraint* constraints, + const if_deadline deadline) + { return m_config.guard(constraints, deadline); } + inline int set(if_clock_type* clock, + const if_time_value value, + const if_pid_type pid) + { return m_config.set(clock,value, pid); } + inline int reset(if_clock_type* clock) + { return m_config.reset(clock); } + inline int active(const if_clock_type clock) + { return m_config.active(clock); } + inline int timeval(const if_clock_type clock) + { return m_config.timeval(clock); } + + public: + inline int acquire(const if_pid_type locker, + const int* resources) + { return m_config.acquire(locker, resources); } + inline int release(const if_pid_type locker, + const int* resources) + { return m_config.release(locker, resources); } + + public: + inline IfInstance* import(const if_pid_type pid) + { trace(IfEvent::IMPORT, m_config.getRunning()->getPid(), "", pid); + return m_config.import(pid); } + inline IfInstance* lightRetrieve(const if_pid_type pid) + { return m_config.import(pid); } + + public: + inline int fetchPid(const if_pid_type proc) + { return m_config.fetchPid(proc); } + inline if_pid_type getPid(const int i) const + { return m_config.getPid(i); } + + public: + inline void setPriority(const int priority) + { m_priority = priority; } + void step(); + + public: + inline void setCutOnError() { m_nCutFlags |= ON_ERROR; } + inline void setCutOnSuccess() { m_nCutFlags |= ON_SUCCESS; } + + public: + DECLARE_RECORDABLE(IfIterator) + + public: + virtual IfConfig* start(); + virtual void run(const IfConfig* source); + + protected: + IfConfig* m_source; // source configuration + IfConfigHandler m_config; // running configuration handler + IfLabelHandler m_label; // running trace handler + + int m_priority; + int m_complete; + + unsigned m_nCutFlags; + +}; + +/* + * + * If2HopsEngine : interface of iteration loop on configurations + * drives another Engine, and returns a successor only if in the source state + * there is no "tick" transition or there is only a self "tick" + * + */ + + +class If2HopsEngine : public IfEngine, public IfDriver { + + public: + If2HopsEngine(); + If2HopsEngine(const IfEngine* engine, const IfDriver* driver = NULL); + ~If2HopsEngine(); + + // Engine part + public: + virtual IfConfig* start(); + virtual void run(const IfConfig* source); + + // Driver part + public: + virtual void explore(IfConfig* source, + IfLabel* label, + IfConfig* target); + + protected: + struct Successor { + IfConfig* state; + IfLabel* label; + Successor* next; + + Successor(IfConfig* s, IfLabel* l, Successor* n) { state = s; label = l; next = n; } + ~Successor() { if(next) delete next; } + }; + + Successor* m_lSuccessors; +}; + diff --git a/src/simulator/label.C b/src/simulator/label.C new file mode 100644 index 0000000000000000000000000000000000000000..cc3f1da78cb162e91c2e975523866460ebb7bc88 --- /dev/null +++ b/src/simulator/label.C @@ -0,0 +1,340 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * event : implements events + * + */ + +IfEvent* IfEvent::NIL = new IfEvent((unsigned)-1, (unsigned)-1, ""); +const int IfEvent::KINDMASK = 0x0000FFFF; +const int IfEvent::FLAGMASK = 0xFFFF0000; + +const char* IfEvent::SYMBOL[] = { + "i", + "", + "i", + "i", + "i", + "?", + "!", + "@", + "#", + "k", + "t/", + ">", + "<", + "x-", + "p", + "P", + "V", + "i", + "d", + "x-" +}; + +const char* IfEvent::NAME[] = { + "SKIP", + "INFORMAL", + "TASK", + "SET", + "RESET", + "INPUT", + "OUTPUT", + "CALL", + "FORK", + "KILL", + "TICK", + "DELIVER", + "IMPORT", + "LOSS", + "PROBABILITY", + "ACQUIRE", + "RELEASE", + "DELTA", + "DEBUG", + "DISCARD", +}; + +IfEvent::IfEvent(const unsigned data, + const if_pid_type pid, + const char* value, + const if_pid_type auxPid, + IfObject * const auxObj) + : IfObject() { + memset(&m_auxData, 0, sizeof(m_auxData)); + m_data = data; + m_pid = pid; + m_value = strdup(value); + m_auxData.objpid.pid = auxPid; + m_auxData.objpid.obj = auxObj; +} + +IfEvent::IfEvent(const unsigned data, + const if_pid_type pid, + const char* value, + const double auxProbability) + : IfObject() { + memset(&m_auxData, 0, sizeof(m_auxData)); + m_data = data; + m_pid = pid; + m_value = strdup(value); + m_auxData.proba = auxProbability; +} + +IfEvent::IfEvent(const IfEvent& event) + : IfObject() { + m_data = event.m_data; + m_pid = event.m_pid; + m_value = event.m_value ? strdup(event.m_value) : NULL; + memcpy(&m_auxData, &event.m_auxData, sizeof(m_auxData)); +} + +IfEvent::~IfEvent() { + if (m_value) free(m_value); +} + +/* +int IfEvent::isIndependent(const IfString<IfObject>& ls, const IfLabel* myLabel) const + { + if(isIndependent()) return true; + if(getKind() == IMPORT) { + for(unsigned i = 0; ls.getAt(i); i++) { + IfLabel* otherL = (IfLabel*)ls.getAt(i); + if(otherL == myLabel) + continue; + if(myLabel->getAt(0) != NULL && otherL->getAt(0) != NULL && myLabel->getAt(0)->getPid() == otherL->getAt(0)->getPid()) + continue; + for(unsigned j = 0; otherL->getAt(j); j++) { + IfEvent* otherE = otherL->getAt(j); + if(otherE->getPid() == getAuxPid() || ((otherE->getKind() == IMPORT || otherE->getKind() == OUTPUT) && otherE->getAuxPid() == getAuxPid())) { + return false; + } + } + } + return true; + } + return false; + } +*/ + +int IfEvent::compare(const IfEvent* event) const { + int cmp = 0; + if (cmp == 0) cmp = getKind() - event->getKind(); + if (cmp == 0) cmp = m_pid - event->m_pid; + if (cmp == 0) cmp = strcmp(m_value, event->m_value); + if (cmp == 0) cmp = memcmp(&m_auxData, &(event->m_auxData), sizeof(m_auxData)); + return cmp; +} + +long unsigned IfEvent::hash(const unsigned long base) const { + unsigned long key = m_data + m_pid; + for(int i = 0; m_value && m_value[i]; i++) + key += (((unsigned long) m_value[i]) << (i % 6)); + return key % base; +} + +IfEvent* IfEvent::copy() const { + return new IfEvent(*this); +} + +void IfEvent::print(FILE* file) const { + if(m_data == IfEvent::NONE) return; + if(getKind() == IfEvent::PROBABILITY) { + // special print for probability events, complies with BCG_MIN specification of + // probabilistic LTS (see man bcg_min). + // NOTE: the probability Event must be the last in a transition! + fprintf(file,"; prob %.6f", m_auxData.proba); + return; + } + fprintf(file, "<<"); + if_pid_print(m_pid, file); + fprintf(file, " %s", SYMBOL[getKind()]); + if (m_value) fprintf(file, "%s", m_value); + if (getAuxPid()) if_pid_print(getAuxPid(), file); + fprintf(file, ">> "); +} + +void IfEvent::printXML(std::ostream& buf) const { + if(m_data == IfEvent::NONE) return; + buf << "<IfEvent kind='" << NAME[getKind()] << "' "; + if (m_value) + buf << "value='" << m_value << "'"; + buf << ">\n"; + + switch(getKind()) { + case IfEvent::OUTPUT: + buf << "<from>\n"; + if_pid_print_xml(m_pid, buf); + buf << "</from>\n"; + buf << "<via>\n"; + if_pid_print_xml(getAuxPid(), buf); + buf << "</via>\n"; + buf << "<to>\n"; + if_pid_print_xml(((IfMessage*)getAuxObj())->getDestination(), buf); + buf << "</to>\n"; + break; + case IfEvent::FORK: + case IfEvent::KILL: + buf << "<process>\n"; + if_pid_print_xml(getAuxPid(), buf); + buf << "</process>\n"; + buf << "<by>\n"; + if_pid_print_xml(getPid(), buf); + buf << "</by>\n"; + break; + case IfEvent::PROBABILITY: + buf << "<probability>\n"; + buf << m_auxData.proba; + buf << "</probability>\n"; + buf << "<by>\n"; + if_pid_print_xml(m_pid, buf); + buf << "</by>\n"; + break; + case IfEvent::IMPORT: + buf << "<by>\n"; + if_pid_print_xml(m_pid, buf); + buf << "</by>\n"; + buf << "<from>\n"; + if_pid_print_xml(getAuxPid(), buf); + buf << "</from>\n"; + break; + default: + buf << "<by>\n"; + if_pid_print_xml(m_pid, buf); + buf << "</by>\n"; + break; + } + + buf << "</IfEvent>\n"; +} + +IMPLEMENT_STORE(IfEvent,"event") + +/* + * + * label : implements labels + * + */ + +IfLabel* IfLabel::NIL = new IfLabel(1); + +unsigned long IfLabel::EvPrintFilter = 0; + +IfLabel::IfLabel(const unsigned size) + : IfObject(), m_events(size) { +} + +IfLabel::IfLabel(const IfLabel& label) + : IfObject(), m_events(label.m_events) { +} + +IfLabel::~IfLabel() { +} + +int IfLabel::isIndependent(unsigned ind_flags) const { + int independent = 1; + for(int i = 0; getAt(i); i++) + independent &= getAt(i)->isIndependent(ind_flags); + return independent; +} + +/* +int IfLabel::isIndependent(const IfString<IfObject>& es) const { + int independent = 1; + for(int i = 0; getAt(i); i++) + independent &= getAt(i)->isIndependent(es, this); + return independent; +} +*/ + +void IfLabel::strip(int (*Visible)(const IfEvent*)) { + int k = 0; + for(int i = 0; getAt(i); i++) + if (Visible(getAt(i))) + setAt(k++, getAt(i)); + setAt(k++, NULL); +} + +int IfLabel::compare(const IfLabel* label) const { + return m_events.compare(&label->m_events); +} + +long unsigned IfLabel::hash(const unsigned long base) const { + return m_events.hash(base); +} + +IfLabel* IfLabel::copy() const { + return new IfLabel(*this); +} + +void IfLabel::print(FILE* file) const { + for(int i = 0; getAt(i); i++) { + IfEvent* e = getAt(i); + if( !(EvPrintFilter & (1<<e->getKind())) ) { + if(EvPrintFilter & (1<<NL)) fprintf(file,"\n"); + e->print(file); + } + } +} + +/* +void IfLabel::print(FILE* file) const { + for(int i = 0; getAt(i); i++) + getAt(i)->print(file); +} +*/ + +void IfLabel::printXML(std::ostream& buf) const { + buf << "<IfLabel>\n"; + for(int i = 0; getAt(i); i++) { + IfEvent* e = getAt(i); + if( !(EvPrintFilter & (1<<e->getKind())) ) { + e->printXML(buf); + } + } + buf << "</IfLabel>\n"; +} + +IMPLEMENT_STORE(IfLabel,"label") + diff --git a/src/simulator/label.h b/src/simulator/label.h new file mode 100644 index 0000000000000000000000000000000000000000..e0adb9793e3cd05cf2c69c4b27d419c90e03f029 --- /dev/null +++ b/src/simulator/label.h @@ -0,0 +1,226 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * event : defines events + * + */ + +// SOLARIS GCC 3.2 Macro +#ifdef TICK +#undef TICK +#endif + +#ifdef DEBUG +#undef DEBUG +#endif + +extern int labeldebug; +#include <iostream> +using namespace std; + +class IfEvent : public IfObject { + + public: + static IfEvent* NIL; + + public: + enum Kind { + NONE = (unsigned)-1, + SKIP = 0, + INFORMAL = 1, + TASK = 2, + SET = 3, + RESET = 4, + INPUT = 5, + OUTPUT = 6, + CALL = 7, + FORK = 8, + KILL = 9, + TICK = 10, + DELIVER = 11, + IMPORT = 12, + LOSS = 13, + PROBABILITY = 14, + ACQUIRE = 15, + RELEASE = 16, + DELTA = 17, + DEBUG = 18, + DISCARD = 19, + }; + enum Flag { + OWN = 0x00010000 + }; + + public: + IfEvent(const unsigned, + const if_pid_type, + const char*, + const if_pid_type auxPid = 0, + IfObject * const auxObj = NULL); + IfEvent(const unsigned, + const if_pid_type, + const char*, + const double auxProbability); + IfEvent(const IfEvent&); + virtual ~IfEvent(); + + public: + inline unsigned getKind() const + { return m_data & KINDMASK; } + inline unsigned is(const unsigned flag) const + { return m_data & flag; } + inline if_pid_type getPid() const + { return m_pid; } + inline char* getValue() const + { return m_value; } + + public: + inline IfObject* getAuxObj() const + { return m_auxData.objpid.obj; } + inline if_pid_type getAuxPid() const + { return m_auxData.objpid.pid; } + inline if_pid_type getPartner() const // synonim + { return m_auxData.objpid.pid; } + + inline double getAuxProbability() const + { return m_auxData.proba; } + + public: + inline int isIndependent(unsigned ind_flags) const + { return + getKind() == DELTA || + getKind() == DEBUG || + getKind() == SKIP || + getKind() == TASK || + getKind() == SET || + getKind() == RESET || + getKind() == INPUT || + getKind() == RELEASE || + getKind() == CALL || + (getKind() == IMPORT && (ind_flags & (1 << getKind()))) || + (getKind() == OUTPUT && (ind_flags & (1 << getKind()))) || + (getKind() == INFORMAL && !strncmp(m_value, "--", 2)) || + getKind() == FORK; + } + + /*inline int isIndependent(const IfString<IfObject>& ls, const IfLabel* myLabel) const;*/ + + + public: + DECLARE_STORABLE(IfEvent) + DECLARE_STORE(IfEvent) + + protected: + static const int KINDMASK; + static const int FLAGMASK; + + static const char* SYMBOL[]; + static const char* NAME[]; + + protected: + unsigned m_data; + if_pid_type m_pid; + char* m_value; + + // auxiliary data + union { + struct { + IfObject* obj; + if_pid_type pid; + } objpid; + + double proba; + } m_auxData; +}; + +/* + * + * label : defines labels as sequences of events + * + */ + +class IfLabel : public IfObject { + + public: + static IfLabel* NIL; + + protected: + static unsigned long EvPrintFilter; + public: + enum EvPrintFlag { + NL = 31, + }; + + public: + IfLabel(const unsigned = 0); + IfLabel(const IfLabel&); + virtual ~IfLabel(); + + public: + inline int getLength() const + { return m_events.getLength(); } + inline IfEvent* getAt(const int i) const + { return m_events.getAt(i); } + void setAt(const int i, const IfEvent* event) + { m_events.setAt(i, (IfEvent*) event); } + static void setEvPrintFilter(const unsigned long pEvPrintFilter) + { EvPrintFilter = pEvPrintFilter; } + + public: + inline if_pid_type getPid() const + { return getAt(0)->getPid(); } + + int isIndependent(unsigned ind_flags) const; + //int isIndependent(const IfString<IfObject>& es) const; + + public: + void strip(int (*Visible)(const IfEvent*)); + + public: + DECLARE_STORABLE(IfLabel); + DECLARE_STORE(IfLabel); + + protected: + IfString<IfEvent> m_events; + +}; + diff --git a/src/simulator/monitor.C b/src/simulator/monitor.C new file mode 100644 index 0000000000000000000000000000000000000000..38f9f9062470fb6357006bb8091a1e91a32588ef --- /dev/null +++ b/src/simulator/monitor.C @@ -0,0 +1,162 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * monitor : implements resource monitors + * + */ + +const char* IfMonitor::NAME = IfInstance::PROCNAME[PROCMAXNUM-2] = "monitor"; + +IfMonitor::Resource IfMonitor::TABLE[RESMAXNUM]; + +int IfMonitor::SIZE = 0; + +int IfMonitor::Register(const int index, const char* name) { + if (SIZE <= index) + SIZE = index + 1; + TABLE[index].name = strdup(name); + return index; +} + +/* + * + * + * + */ + +IfMonitor::IfMonitor() + : IfInstance(if_pid_mk(PROCMAXNUM-2,0)) { + m_table = new resource[SIZE]; + for(int i = 0; i < SIZE; i++) + m_table[i].locker = 0; // nil +} + +IfMonitor::IfMonitor(const IfMonitor& monitor) + : IfInstance(monitor) { + m_table = new resource[SIZE]; + for(int i = 0; i < SIZE; i++) + m_table[i] = monitor.m_table[i]; +} + +IfMonitor::~IfMonitor() { + delete[] m_table; +} + +int IfMonitor::acquire(const if_pid_type locker, + const int* resources) { + int available = 1; + for(int k = 0; resources[k] != -1 && available; k++) { + int i = resources[k]; + if (m_table[i].locker != 0 && + m_table[i].locker != locker) + available = 0; + } + if (available) + for(int k = 0; resources[k] != -1; k++) { + int i = resources[k]; + m_table[i].locker = locker; + } + return available; +} + +int IfMonitor::release(const if_pid_type locker, + const int* resources) { + for(int k = 0; resources[k] != -1; k++) { + int i = resources[k]; + if (m_table[i].locker == locker) + m_table[i].locker = 0; + } + return 1; +} + +void IfMonitor::iterate(IfIterator*) { + // empty +} + +void IfMonitor::copy(const IfInstance* instance) { + IfMonitor* monitor = (IfMonitor*) instance; + for(int i = 0; i < SIZE; i++) + m_table[i] = monitor->m_table[i]; +} + +int IfMonitor::compare(const IfInstance* instance) const { + IfMonitor* monitor = (IfMonitor*) instance; + int cmp = IfInstance::compare(instance); + for(int i = 0; i < SIZE && cmp == 0; i++) + cmp = m_table[i].locker - monitor->m_table[i].locker; + return cmp; +} + +long unsigned IfMonitor::hash(const unsigned long base) const { + unsigned long key = 0; + for(int i = 0; i < SIZE; i++) + key += ((unsigned long) m_table[i].locker) << (i % 7); + return key % base; +} + +IfInstance* IfMonitor::copy() const { + return new IfMonitor(*this); +} + +void IfMonitor::print(FILE* file) const { + IfInstance::print(file); + fprintf(file, "\n @run\t\t"); + for(int i = 0; i < SIZE; i++) + if (m_table[i].locker != 0) { + fprintf(file, "%s@", TABLE[i].name); + if_pid_print(m_table[i].locker, file); + fprintf(file, " "); + } +} +void IfMonitor::printXML(std::ostream& buf) const { + buf << "<IfMonitor>\n"; + for(int i = 0; i < SIZE; i++) { + buf << "<IfRessource name='" << TABLE[i].name << "' >\n"; + buf << "<owner>"; + if_pid_print_xml(m_table[i].locker, buf); + buf << "</owner>\n"; + buf << "</IfRessource>\n"; + } + buf << "</IfMonitor>\n"; +} diff --git a/src/simulator/monitor.h b/src/simulator/monitor.h new file mode 100644 index 0000000000000000000000000000000000000000..01d3ab1abff6aa5a81c962c23b88b298390c6b41 --- /dev/null +++ b/src/simulator/monitor.h @@ -0,0 +1,94 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * monitor : defines resource monitors + * + */ + +#define RESMAXNUM 128 + +class IfMonitor : public IfInstance { + + protected: + struct Resource { + char* name; + // to be completed (e.g, type) + }; + + protected: + static Resource TABLE[RESMAXNUM]; + static int SIZE; + + public: + static const char* NAME; + + public: + static int Register(const int index, + const char* name); + + + public: + IfMonitor(); + IfMonitor(const IfMonitor&); + virtual ~IfMonitor(); + + public: + virtual int acquire(const if_pid_type, const int*); + virtual int release(const if_pid_type, const int*); + + public: + virtual void iterate(IfIterator*); + virtual void copy(const IfInstance*); + + public: + DECLARE_STORABLE(IfInstance) + + protected: + struct resource { + if_pid_type locker; + // to be completed (e.g, count) + }; + + protected: + resource* m_table; + +}; diff --git a/src/simulator/object.C b/src/simulator/object.C new file mode 100644 index 0000000000000000000000000000000000000000..4b810f4b81423910acbb11d9ecb950e191d07d05 --- /dev/null +++ b/src/simulator/object.C @@ -0,0 +1,84 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * object : implements very abstract objects + * + */ + +FILE* IfObject::FBUF = tmpfile(); // opened in /tmp/... + +char IfObject::SBUF[SBUFMAXSIZE]; + +IfObject::IfObject() { +} + +IfObject::IfObject(const IfObject&) { +} + +IfObject::~IfObject() { +} + +void IfObject::print(FILE*) const { + // pure virtual +} + +void IfObject::sprint() const { + // pure virtual +} + +char* IfObject::string() const { + print(FBUF); fprintf(FBUF, "%c", 0); + rewind(FBUF); + fread(SBUF, 1, SBUFMAXSIZE, FBUF); + rewind(FBUF); + return SBUF; +} + +/* +char* IfObject::string() const { + SBUF[0] = '\0'; + sprint(); + return SBUF; +} +*/ diff --git a/src/simulator/object.h b/src/simulator/object.h new file mode 100644 index 0000000000000000000000000000000000000000..39bcf9f021f1aa0fe04b6746a5587a3d2dbb68b1 --- /dev/null +++ b/src/simulator/object.h @@ -0,0 +1,68 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * object : defines very abstract objects + * + */ + +#define SBUFMAXSIZE 65536 + +class IfObject { + + public: + IfObject(); + IfObject(const IfObject&); + virtual ~IfObject(); + + public: + virtual void print(FILE* file) const; + virtual void printXML(std::ostream& buf) const = 0; + virtual void sprint() const; + + public: + virtual char* string() const; + + protected: + static FILE* FBUF; + static char SBUF[SBUFMAXSIZE]; + +}; diff --git a/src/simulator/observer.C b/src/simulator/observer.C new file mode 100644 index 0000000000000000000000000000000000000000..0604f5694e227cd21d977edf7caa186f114c800c --- /dev/null +++ b/src/simulator/observer.C @@ -0,0 +1,418 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * IfObserverInstance : base class for user observer instances + * + */ + +IfObserverInstance::IfObserverInstance(if_pid_type pid, IfQueue* queue) + : IfInstance(pid, queue) { + m_curLabel = IfLabel::NIL; + m_bCut = 0; +} + +IfObserverInstance::IfObserverInstance(const IfObserverInstance& instance) + : IfInstance(instance) { + m_curLabel = instance.m_curLabel; + m_bCut = instance.m_bCut; +} + +void IfObserverInstance::copy(const IfInstance* inst) { + IfObserverInstance* obs = (IfObserverInstance*)inst; + + m_curLabel = obs->m_curLabel; + m_bCut = obs->m_bCut; + +} + +unsigned IfObserverInstance::if_pid_obs_queue_length(const if_pid_type pid) const { + IfInstance* inst = ITERATOR->import(pid); + if(!inst) return 0; + return inst->GetQueue()->GetLength(); +} + +IfObserverInstance::~IfObserverInstance() { +} + +int IfObserverInstance::trace(const IfEvent* event) { + int len = m_curLabel->getLength(); + IfLabel* l = new IfLabel(len+2); + for (int i = 0; i < len; i++) + l->setAt(i, m_curLabel->getAt(i)); + l->setAt(len, event); + l->setAt(len+1, NULL); + m_curLabel = l->store(); + + return 1; +} + +void IfObserverInstance::flushLabel() { + m_curLabel = IfLabel::NIL; +} + +// STORABLE INTERFACE +int IfObserverInstance::compare(const IfInstance* instance) const { + IfObserverInstance* obs = (IfObserverInstance*)instance; + int cmp = IfInstance::compare(instance); + if (cmp == 0) cmp = (long) m_curLabel - (long) obs->m_curLabel; + if (cmp == 0) cmp = m_bCut - obs->m_bCut; + return cmp; +} + +long unsigned IfObserverInstance::hash(const unsigned long base) const { + return ((m_pid + ((unsigned long) m_curLabel)) >> 4) % base; +} + +IfInstance* IfObserverInstance::copy() const { + return new IfObserverInstance(*this); +} + +void IfObserverInstance::print(FILE* file) const { + if_pid_print(m_pid,file); + fprintf(file, "\t\t{{"); + m_curLabel->print(file); + fprintf(file, "}} %s", m_bCut ? "cut!" : ""); +} + +void IfObserverInstance::printXML(std::ostream& buf) const { + buf << "<self>\n"; + if_pid_print_xml(m_pid,buf); + buf << "</self>\n"; + + buf << "<eventset>\n"; + m_curLabel->printXML(buf); + buf << "</eventset>\n"; +} + +IfMessage* IfObserverInstance::if_pid_obs_queue_get_first(if_pid_type pid) { + IfInstance* inst = ITERATOR->lightRetrieve(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + return (IfMessage*)inst->GetQueue()->getHead(); +} + +IfMessage* IfObserverInstance::if_pid_obs_queue_get_last(if_pid_type pid) { + IfInstance* inst = ITERATOR->lightRetrieve(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + return (IfMessage*)inst->GetQueue()->getTailMessage(); +} + +IfMessage* IfObserverInstance::if_pid_obs_queue_get_at(if_pid_type pid, if_integer_type i) { + IfInstance* inst = ITERATOR->lightRetrieve(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + return (IfMessage*)inst->GetQueue()->getMessageAt(i); +} + +IfMessage* IfObserverInstance::if_pid_obs_queue_remove_first(if_pid_type pid) { + IfMessage* res; + IfInstance* inst = ITERATOR->lightRetrieve(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + inst->RemoveFromQueue(res = (IfMessage*)inst->GetQueue()->getHead()); + return res; +} + +IfMessage* IfObserverInstance::if_pid_obs_queue_remove_last(if_pid_type pid) { + IfMessage* res; + IfInstance* inst = ITERATOR->lightRetrieve(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + inst->RemoveFromQueue(res = (IfMessage*)inst->GetQueue()->getTailMessage()); + return res; +} + +IfMessage* IfObserverInstance::if_pid_obs_queue_remove_at(if_pid_type pid, if_integer_type i) { + IfMessage* res; + IfInstance* inst = ITERATOR->lightRetrieve(pid); + if( !inst || inst->GetQueue() == IfQueue::NIL) return NULL; + inst->RemoveFromQueue(res = (IfMessage*)inst->GetQueue()->getMessageAt(i)); + return res; +} + +IfMessage* IfObserverInstance::if_obs_input(unsigned sid, if_pid_type pid) { + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::INPUT && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid) && + (pid == (unsigned)-1 || pid == evt->getAuxPid() ) ) { + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +IfMessage* IfObserverInstance::if_obs_input_ext(unsigned sid, if_pid_type* pid) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::INPUT && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid ) ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + if(pid != NULL) *pid = evt->getAuxPid(); + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +IfMessage* IfObserverInstance::if_obs_discard(unsigned sid, if_pid_type pid) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::DISCARD && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid) && + (pid == (unsigned)-1 || pid == evt->getAuxPid() ) ) { + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +IfMessage* IfObserverInstance::if_obs_discard_ext(unsigned sid, if_pid_type* pid) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::DISCARD && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid ) ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + if(pid != NULL) *pid = evt->getAuxPid(); + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +IfMessage* IfObserverInstance::if_obs_output(unsigned sid, unsigned index, if_pid_type from, if_pid_type via, if_pid_type to) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::OUTPUT && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid) && + (from == (unsigned)-1 || from == evt->getPid()) && + (via == (unsigned)-1 || via == evt->getAuxPid()) && + (to == (unsigned)-1 || (via == (unsigned)-1 && to == evt->getAuxPid()) || (via != (unsigned)-1 && to == ((IfMessage*)evt->getAuxObj())->getDestination())) && + !(index--) ) { + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +IfMessage* IfObserverInstance::if_obs_output_ext(unsigned sid, unsigned index, if_pid_type* from, if_pid_type* via, if_pid_type* to) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::OUTPUT && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid ) && + !(index--) ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + if(from != NULL) *from = evt->getPid(); + if(via != NULL) *via = evt->getAuxPid(); + if(to != NULL) { + if(via != NULL) *to = ((IfMessage*)evt->getAuxObj())->getDestination(); + else *to = evt->getAuxPid(); + } + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +if_boolean_type IfObserverInstance::if_obs_fork(unsigned process, if_pid_type in) { + if_boolean_type res = 0; + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::FORK && + ( process == (unsigned)-1 || process == if_pid_proc(evt->getAuxPid()) ) && + ( in == (unsigned)-1 || in == evt->getPid() ) ) { + + res = 1; + break; + } + } + return res; +} + +void IfObserverInstance::if_obs_fork_ext(unsigned process, if_pid_type* var, if_pid_type* in) { + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::FORK && + ( process == (unsigned)-1 || process == if_pid_proc(evt->getAuxPid()) ) ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + if(var != NULL) *var = evt->getAuxPid(); + if(in != NULL) *in = evt->getPid(); + return ; + } + } + if(var != NULL) *var = (unsigned)-1; + return ; +} + +if_boolean_type IfObserverInstance::if_obs_kill(unsigned process, if_pid_type pid, if_pid_type in) { + if_boolean_type res = 0; + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::KILL && + ( process == (unsigned)-1 || if_pid_proc( evt->getAuxPid() ) == process ) && + ( pid == (unsigned)-1 || pid == evt->getAuxPid() ) && + ( in == (unsigned)-1 || in == evt->getPid() ) ) { + + res = 1; + break; + } + } + return res; +} + +void IfObserverInstance::if_obs_kill_ext(unsigned process, if_pid_type* var, if_pid_type* in) { + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::KILL && + ( process == (unsigned)-1 || if_pid_proc( evt->getAuxPid() ) == process ) ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + if(var != NULL) *var = evt->getAuxPid(); + if(in != NULL) *in = evt->getPid(); + return ; + } + } + if(var != NULL) *var = (unsigned)-1; + return ; +} + +IfMessage* IfObserverInstance::if_obs_deliver(unsigned sid, if_pid_type from) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::DELIVER && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid) && + (from == (unsigned)-1 || from == evt->getPid()) ) { + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +IfMessage* IfObserverInstance::if_obs_deliver_ext(unsigned sid, if_pid_type* from) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::DELIVER && + (sid == (unsigned)-1 || ((IfMessage*)evt->getAuxObj())->getSid() == sid ) ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + if(from != NULL) *from = evt->getPid(); + return (IfMessage*)evt->getAuxObj(); + } + } + return NULL; +} + +if_boolean_type IfObserverInstance::if_obs_informal(char* name, if_pid_type in) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::INFORMAL && + ( name == NULL || !strcmp(name,(char*)evt->getAuxObj()) ) && + ( in == (unsigned)-1 || in == evt->getPid() ) ) { + return 1; + } + } + return 0; +} + +void IfObserverInstance::if_obs_informal_ext(char* name, if_pid_type* in) +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::INFORMAL && + ( name == NULL || !strcmp(name,(char*)evt->getAuxObj()) ) ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + if(in != NULL) *in = evt->getPid(); + return; + } + } +} + +if_boolean_type IfObserverInstance::if_obs_probability() +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::PROBABILITY ) { + return 1; + } + } + return 0; +} + +if_real_type IfObserverInstance::if_obs_probability_ext() +{ + for(int i = 0; i < m_curLabel->getLength(); i++) { + IfEvent* evt = m_curLabel->getAt(i); + + if ( evt->getKind() == IfEvent::PROBABILITY ) { + m_curLabel = m_curLabel->copy(); + m_curLabel->setAt(i, IfEvent::NIL); + return evt->getAuxProbability(); + } + } + return 1; +} diff --git a/src/simulator/observer.h b/src/simulator/observer.h new file mode 100644 index 0000000000000000000000000000000000000000..65889c3ccd4c85bace55d71651e93dd6bd510f84 --- /dev/null +++ b/src/simulator/observer.h @@ -0,0 +1,102 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * IfObserverInstance : base class for user observer instances + * + */ + +#define OBSERVER_PRIORITY 0xFFFF + +class IfObserverInstance : public IfInstance { + + public: + IfObserverInstance(if_pid_type = 0, IfQueue* = IfQueue::NIL); + IfObserverInstance(const IfObserverInstance&); + virtual ~IfObserverInstance(); + + public: + virtual int getPriority() const + { return OBSERVER_PRIORITY; } + + public: + virtual void copy(const IfInstance*); + + public: + DECLARE_STORABLE(IfInstance) + + protected: + unsigned if_pid_obs_queue_length(const if_pid_type pid) const; + + protected: + IfLabel* m_curLabel; + public: + int trace(const IfEvent* event); + void flushLabel(); + void cut() { m_bCut = 1; } + + virtual int isCut() const { return m_bCut; } + IfMessage* if_pid_obs_queue_get_first(if_pid_type pid); + IfMessage* if_pid_obs_queue_get_last(if_pid_type pid); + IfMessage* if_pid_obs_queue_get_at(if_pid_type pid, if_integer_type i); + IfMessage* if_pid_obs_queue_remove_first(if_pid_type pid); + IfMessage* if_pid_obs_queue_remove_last(if_pid_type pid); + IfMessage* if_pid_obs_queue_remove_at(if_pid_type pid, if_integer_type i); + IfMessage* if_obs_input(unsigned sid, if_pid_type pid); + IfMessage* if_obs_input_ext(unsigned sid, if_pid_type* pid); + IfMessage* if_obs_discard(unsigned sid, if_pid_type pid); + IfMessage* if_obs_discard_ext(unsigned sid, if_pid_type* pid); + IfMessage* if_obs_output(unsigned sid, unsigned index, if_pid_type from, if_pid_type via, if_pid_type to); + IfMessage* if_obs_output_ext(unsigned sid, unsigned index, if_pid_type* from, if_pid_type* via, if_pid_type* to); + if_boolean_type if_obs_fork(unsigned process, if_pid_type in); + void if_obs_fork_ext(unsigned process, if_pid_type* var, if_pid_type* in); + if_boolean_type if_obs_kill(unsigned process, if_pid_type pid, if_pid_type in); + void if_obs_kill_ext(unsigned process, if_pid_type* pid, if_pid_type* in); + IfMessage* if_obs_deliver(unsigned sid, if_pid_type from); + IfMessage* if_obs_deliver_ext(unsigned sid, if_pid_type* from); + if_boolean_type if_obs_informal(char* name, if_pid_type in); + void if_obs_informal_ext(char* name, if_pid_type* in); + if_boolean_type if_obs_probability(); + if_real_type if_obs_probability_ext(); + + unsigned m_bCut; +}; + diff --git a/src/simulator/queue.C b/src/simulator/queue.C new file mode 100644 index 0000000000000000000000000000000000000000..c8673508d3d85cb20c61490a96143bc456b35f17 --- /dev/null +++ b/src/simulator/queue.C @@ -0,0 +1,226 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * message : implements abstract messages + * + */ + +const char* IfMessage::SIGNAME[SIGMAXNUM]; + +IfMessage::IfMessage(const unsigned sid, + const if_pid_type destination, + const if_clock_type wait) + : IfObject() { + m_sid = sid; + m_destination = destination; + m_wait = wait; +} + +IfMessage::IfMessage(const IfMessage& message) + : IfObject(message) { + m_sid = message.m_sid; + m_destination = message.m_destination; + m_wait = message.m_wait; +} + +IfMessage::~IfMessage() { +} + +int IfMessage::compare(const IfMessage* message) const { + int cmp = 0; + if (cmp == 0) cmp = (int) m_sid - (int) message->m_sid; + if (cmp == 0) cmp = (int) m_destination - (int) message->m_destination; + if (cmp == 0) cmp = (int) m_wait - (int) message->m_wait; + return cmp; +} + +unsigned long IfMessage::hash(const unsigned long base) const { + return (m_sid + m_destination) % base; +} + +IfMessage* IfMessage::copy() const { + return new IfMessage(*this); +} + +void IfMessage::print(FILE* file) const { + // fprintf(file, "%d", m_sid); + if (m_destination != 0) { + fprintf(file, "#"); + if_pid_print(m_destination, file); + } + if (m_wait != -1) { + fprintf(file, "#"); + if_clock_print(m_wait, file); + } +} + +void IfMessage::printXML(std::ostream& buf) const { + if (m_destination != 0) { + buf << "<destination>\n"; + if_pid_print_xml(m_destination, buf); + buf << "</destination>\n"; + } + if (m_wait != -1) { + buf << "<wait>\n"; + if_clock_print_xml(m_wait, buf); + buf << "</wait>\n"; + } +} + +void IfMessage::sprint() const { + char tmp[SBUFMAXSIZE]; + if (m_destination != 0) { + strcat(SBUF, "#"); + if_pid_sprint(m_destination, tmp); strcat(SBUF, tmp); + } + if (m_wait != -1) { + strcat(SBUF, "#"); + if_clock_sprint(m_wait, tmp); strcat(SBUF, tmp); + } +} + +IMPLEMENT_STORE(IfMessage,"message") + +/* + * + * queue : implements message queues + * + */ + +IfQueue* IfQueue::NIL = new IfQueue; + +IfQueue::IfQueue(const IfMessage* message, const IfQueue* queue) + : IfObject() { + m_head = message; + m_tail = queue; +} + +IfQueue::IfQueue(const IfQueue& queue) + : IfObject(queue) { + m_head = queue.m_head; + m_tail = queue.m_tail; +} + +IfQueue::~IfQueue() { +} + +const IfMessage* IfQueue::getTailMessage() const { + if( this == NIL ) return NULL; + if( m_tail == NIL ) return m_head; + return m_tail->getTailMessage(); +} + +const IfMessage* IfQueue::getMessageAt(int i) const { + if( this == NIL ) return NULL; + if( i == 0 ) return m_head; + return m_tail->getMessageAt(i-1); +} + +IfQueue* IfQueue::putHead(const IfMessage* message) const { + IfQueue queue; + queue.m_head = message; + queue.m_tail = this; + return queue.store(); +} + +IfQueue* IfQueue::putTail(const IfMessage* message) const { + return this == NIL ? putHead(message) : + m_tail->putTail(message)->putHead(m_head); +} + +IfQueue* IfQueue::remove(const IfMessage* message) const { + return this == NIL ? NIL : + m_head == message ? (IfQueue*) m_tail : + m_tail->remove(message)->putHead(m_head); +} + +int IfQueue::GetLength() const { + if(this == NIL) return 0; + return 1 + m_tail->GetLength(); +} + +IfQueue* IfQueue::insert(const IfMessage* message) const { + // assume increasing order for messages (multiset buffers) + return this == NIL ? putHead(message) : + m_head->compare(message) >= 0 ? putHead(message) : + m_tail->insert(message)->putHead(m_head); +} + +int IfQueue::compare(const IfQueue* queue) const { + int cmp = 0; + if (cmp == 0) cmp = (long) m_head - (long) queue->m_head; + if (cmp == 0) cmp = (long) m_tail - (long) queue->m_tail; + return cmp; +} + +unsigned long IfQueue::hash(const unsigned long base) const { + return ( (((unsigned long) m_head) >> 4) + + (((unsigned long) m_tail) >> 2) ) % base; +} + +IfQueue* IfQueue::copy() const { + return new IfQueue(*this); +} + +void IfQueue::print(FILE* file) const { + if (this == NIL) + return; + m_head->print(file); + if (m_tail != NIL) { + fprintf(file, ","); + m_tail->print(file); + } +} + +void IfQueue::printXML(std::ostream& buf) const { + if (this == NIL) + return; + m_head->printXML(buf); + if (m_tail != NIL) { + m_tail->printXML(buf); + } +} + +IMPLEMENT_STORE(IfQueue,"queue") + diff --git a/src/simulator/queue.h b/src/simulator/queue.h new file mode 100644 index 0000000000000000000000000000000000000000..8cdb8335019160551d4100b0bdfb0c76228199d1 --- /dev/null +++ b/src/simulator/queue.h @@ -0,0 +1,132 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * message : defines abstract messages + * + */ + +#define SIGMAXNUM 256 + +class IfMessage : public IfObject { + + public: + IfMessage(const unsigned sid, + const if_pid_type destination = 0, + const if_clock_type wait = -1); + IfMessage(const IfMessage&); + virtual ~IfMessage(); + + public: + inline unsigned getSid() const + { return m_sid; } + inline if_pid_type getDestination() const + { return m_destination; } + inline if_clock_type getWait() const + { return m_wait; } + + inline void setDestination(const if_pid_type destination) + { m_destination = destination; } + inline void setWait(const if_clock_type wait) + { m_wait = wait; } + + public: + DECLARE_STORABLE(IfMessage) + virtual void sprint() const; + DECLARE_STORE(IfMessage) + + public: + virtual int GetParSize() const { return 0; } + virtual void* GetParAddress() const { return (void*)this; } + public: + static const char* SIGNAME[SIGMAXNUM]; + + protected: + unsigned m_sid; + if_pid_type m_destination; // buffer use + if_clock_type m_wait; // buffer use + +}; + +/* + * + * queue : define message queues + * + */ + +class IfQueue : public IfObject { + + public: + static IfQueue* NIL; + + public: + IfQueue(const IfMessage* = NULL, const IfQueue* = NULL); + IfQueue(const IfQueue&); + virtual ~IfQueue(); + + public: + inline const IfMessage* getHead() const + { return m_head; } + inline const IfQueue* getTail() const + { return m_tail; } + const IfMessage* getTailMessage() const; + const IfMessage* getMessageAt(int i) const; + + public: + IfQueue* putHead(const IfMessage*) const; + IfQueue* putTail(const IfMessage*) const; + + public: + IfQueue* remove(const IfMessage*) const; + + public: + int GetLength() const; + IfQueue* insert(const IfMessage*) const; + + public: + DECLARE_STORABLE(IfQueue); + DECLARE_STORE(IfQueue); + + protected: + const IfMessage* m_head; + const IfQueue* m_tail; + +}; diff --git a/src/simulator/simulator.C b/src/simulator/simulator.C new file mode 100644 index 0000000000000000000000000000000000000000..57b491c3ec4938dbb634711bff7f995d4e679e1a --- /dev/null +++ b/src/simulator/simulator.C @@ -0,0 +1,88 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +unsigned long if_hash(const char* data, + const unsigned size, + const unsigned long base) { + unsigned long key = 0; + for(unsigned i = 0; i < size; i++){ + unsigned x = data[i]; + key += x << ((i % 4) << 2); + } + return key % base; +} + +/* + * Give the next prime number after the start value. + * Used to compute the hash table and the cache sizes. + * + */ +unsigned long if_nextprime(const unsigned long start) { + unsigned long p = 2; + if (start < 2) + return p; + for(p = start;; p++) + if (p % 2) + for(unsigned long k = 3;; k += 2) { + if (p / k < k) + return p; + if (! (p % k)) + break; + } + return p; +} + +/* + * + * options + * + */ + +unsigned opt_use_priorities = 0; // for observers, for the moment +unsigned opt_gen_lineno = 0; +unsigned opt_discard = 0; + +IfDynamicError::IfDynamicError(int p_code) +{ + m_code = p_code; +} + diff --git a/src/simulator/simulator.h b/src/simulator/simulator.h new file mode 100644 index 0000000000000000000000000000000000000000..b09b318f43f2904bade847390600d9e19419c6e2 --- /dev/null +++ b/src/simulator/simulator.h @@ -0,0 +1,212 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * IF simulator interface + * + */ + +#ifndef SIMULATOR_H +#define SIMULATOR_H + +#include <sstream> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +/* + * + * generic components + * + */ + +template <class C> + class IfString; +template <class C, unsigned L> + class IfChunk; +template <typename T> + class IfVector; +template <class C> + class IfLinkedList; +template <unsigned L> + class IfBitVector; + +template <class C> + class IfTable; +template <class C> + class IfTreeTable; +template <class C> + class IfHashTable; + +/* + * + * specific components + * + */ + +template <unsigned L, typename T> + struct if_state; + +class IfObject; + class IfMessage; + class IfQueue; + class IfInstance; + class IfTime; + class IfDiscreteTime; + class IfContinuousTime; + class IfMonitor; + class IfBuffer; + class IfObserverInstance; + class IfPacket; + class IfConfig; + class IfEvent; + class IfLabel; + +class IfHandler; + class IfInstanceHandler; + class IfConfigHandler; + class IfLabelHandler; + + +class IfEngine; + class IfIterator; + +class IfDriver; + +class IfDynamicError { + // exception class +public: + const static int IAF = 1 ; + +protected: + int m_code; + +public: + IfDynamicError(int p_code); +}; + +/* + * + * macros + * + */ + +#define DECLARE_STORABLE(Class) \ + virtual int compare(const Class*) const; \ + virtual unsigned long hash(const unsigned long) const; \ + virtual Class* copy() const; \ + virtual void print(FILE*) const; \ + virtual void printXML(std::ostream&) const; + +#define DECLARE_STORE(Class) \ + static IfHashTable<Class> STORE; \ + virtual Class* store() const; + +#define IMPLEMENT_STORE(Class,Name) \ + IfHashTable<Class> Class::STORE(Name); \ + Class* Class::store() const { \ + return STORE.store(this); \ + } + +#define DECLARE_RECORDABLE(Class) \ + virtual void record(); \ + virtual void restore(); \ + virtual void forget(); \ + virtual void print(FILE*) const; + + +#ifdef DEBUG +#define TRACE(block) block +#else +#define TRACE(block) +#endif + +/* + * + * functions + * + */ + +unsigned long if_hash(const char*, + const unsigned, + const unsigned long); + +unsigned long if_nextprime(const unsigned long); + +/* + * + * execution options + * + */ + +extern unsigned opt_use_priorities; // for observers, for the moment +extern unsigned opt_gen_lineno; // for observers, for the moment +extern unsigned opt_discard; // for observers, for the moment + +/* + * + * header files + * + */ + +#include "base.h" +#include "base.i" +#include "structure.h" +#include "structure.i" +#include "table.h" +#include "table.i" + +#include "object.h" +#include "queue.h" +#include "instance.h" +#include "observer.h" +#include "xtime.h" +#include "monitor.h" +#include "buffer.h" +#include "config.h" +#include "label.h" + +#include "engine.h" +#include "iterator.h" + +#endif diff --git a/src/simulator/structure.h b/src/simulator/structure.h new file mode 100644 index 0000000000000000000000000000000000000000..ce91847a51f7355429e0376cb7b92133f018d8de --- /dev/null +++ b/src/simulator/structure.h @@ -0,0 +1,251 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * string : defines null-terminated pointer strings + * + */ + +template <class C> +class IfString { + + public: + IfString(const int = 0); + IfString(const IfString<C>&); + virtual ~IfString(); + + public: + inline C* getAt(const int i) const + { return m_objects[i]; } + inline void setAt(const int i, const C* object) + { m_objects[i] = (C*) object; } + int getLength() const; + + public: + DECLARE_STORABLE(IfString<C>) + + protected: + C* *m_objects; + +}; + +/* + * + * chunk : defines fixed-length pointer chunks + * + */ + +template <class C, unsigned L> +class IfChunk { + + public: + IfChunk(); + IfChunk(const IfChunk<C,L>&); + virtual ~IfChunk(); + + public: + inline C* getAt(const int i) const + { return m_objects[i]; } + inline void setAt(const int i, const C* object) + { m_objects[i] = (C*) object; } + inline int getLength() const + { return (int) L; } + + public: + // DECLARE_STORABLE(IfChunk<C,L>) + virtual int compare(const IfChunk<C,L>*) const; + virtual unsigned long hash(const unsigned long) const; + virtual IfChunk<C,L>* copy() const; + virtual void print(FILE*) const; + virtual void xmlize(FILE*) const; + + protected: + C* m_objects[L]; + +}; + +/* + * + * vector : defines variable-length vectors + * + */ + +template <typename T> +class IfVector { + + public: + IfVector(const int = 0); + IfVector(const IfVector<T>&); + virtual ~IfVector(); + + public: + inline int getLength() const + { return m_length; } + inline T getAt(const int i) const + { return m_data[i]; } + inline void setAt(const int i, const T t) + { m_data[i] = t; } + + public: + int find(const T) const; + void insert(const int, const T); + void remove(const int); + + public: + DECLARE_STORABLE(IfVector<T>); + void copy(const IfVector<T>*); + + protected: + int m_length; + T* m_data; + +}; + +/* + * + * list : defines double-linked dynamic lists + * + */ + +template <class C> +class IfLinkedList { + + public: + IfLinkedList(); + virtual ~IfLinkedList(); + + public: + struct Node { + C* m_object; + Node* m_prev; + Node* m_next; + }; + + public: + inline C* getAt(const Node* node) const + { return node->m_object; } + inline void setAt(Node* node, const C* object) const + { node->m_object = object; } + + public: + inline Node* getFirst() const + { return m_first; } + inline Node* getLast() const + { return m_last; } + inline Node* getNext(const Node* node) const + { return node->m_next; } + inline Node* getPrev(const Node* node) const + { return node->m_prev; } + + public: + void insert(const C*, Node* = NULL); + void append(const C*, Node* = NULL); + void remove(Node*); + void purge(); + + protected: + Node* m_first; + Node* m_last; + +}; + +/* + * + * heap : defines dynamic heaps + * + */ + +template <class C> +class IfHeap { + + public: + IfHeap(); + virtual ~IfHeap(); + + public: + inline int getCount() const + { return m_count; } + + public: + C* get(); + void put(const C*); + + protected: + int m_length; + C* *m_objects; + + int m_count; + +}; + +/* + * + * bit vector : defines fixed-length bit vectors + * + */ + +template <unsigned L> +class IfBitVector { + + public: + IfBitVector(); + IfBitVector(const IfBitVector<L>&); + virtual ~IfBitVector(); + + public: + int in(const int) const; // in test + void set(const int); // setting + void reset(const int); // resetting + + public: + unsigned cardinal() const; // cardinal + int ord(const int) const; // index ordinal + int first() const; // first zero index + int last() const; // last one index + + public: + DECLARE_STORABLE(IfBitVector<L>) + void copy(const IfBitVector<L>*); + + protected: + unsigned char m_data[L]; + +}; diff --git a/src/simulator/structure.i b/src/simulator/structure.i new file mode 100644 index 0000000000000000000000000000000000000000..1e8e29513fb801027a589cdf69466131b29c4cc4 --- /dev/null +++ b/src/simulator/structure.i @@ -0,0 +1,548 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * string : implementats null-terminated pointer strings + * + */ + +template <class C> +IfString<C>::IfString(const int len) { + m_objects = new C* [len]; + for(int i = 0; i < len; i++) + m_objects[i] = NULL; +} + +template <class C> +IfString<C>::IfString(const IfString<C>& string) { + int len = string.getLength(); + m_objects = new C* [len + 1]; + for(int i = 0; i <= len; i++) + m_objects[i] = string.m_objects[i]; +} + +template <class C> +IfString<C>::~IfString() { + delete[] m_objects; +} + +template <class C> +int IfString<C>::getLength() const { + int len = 0; + while (m_objects[len]) + len++; + return len; +} + +template <class C> +int IfString<C>::compare(const IfString<C>* string) const { + int i = 0; + while (m_objects[i] && m_objects[i] == string->m_objects[i]) + i++; + return (long) m_objects[i] - (long) string->m_objects[i]; +} + +template <class C> +unsigned long IfString<C>::hash(const unsigned long base) const { + unsigned long hash = 0; + for(int i = 0; m_objects[i]; i++) + hash += ((unsigned long) m_objects[i]) >> 4; + return hash % base; +} + +template <class C> +IfString<C>* IfString<C>::copy() const { + return new IfString<C>(*this); +} + +template <class C> +void IfString<C>::print(FILE*) const { + // pure virtual +} + +template <class C> +void IfString<C>::printXML(std::ostream&) const { + // pure virtual +} + +/* + * + * chunk : implements fixed-length pointer strings + * + */ + +template <class C, unsigned L> +IfChunk<C,L>::IfChunk() { + for(unsigned i = 0; i < L; i++) + m_objects[i] = NULL; +} + +template <class C, unsigned L> +IfChunk<C,L>::IfChunk(const IfChunk<C,L>& chunk) { + for(unsigned i = 0; i < L; i++) + m_objects[i] = chunk.m_objects[i]; +} + +template <class C, unsigned L> +IfChunk<C,L>::~IfChunk() { +} + +template <class C, unsigned L> +int IfChunk<C,L>::compare(const IfChunk<C,L>* chunk) const { + long cmp = 0; + for(unsigned i = 0; i < L && !cmp; i++) + cmp = (long) m_objects[i] - (long) chunk->m_objects[i]; + + return cmp; +} + +template <class C, unsigned L> +unsigned long IfChunk<C,L>::hash(const unsigned long base) const { + unsigned long hash = 0; + for(unsigned i = 0; i < L; i++) + hash += ((unsigned long) m_objects[i]) >> 4; + return hash % base; +} + +template <class C, unsigned L> +IfChunk<C,L>* IfChunk<C,L>::copy() const { + return new IfChunk<C,L>(*this); +} + +template <class C, unsigned L> +void IfChunk<C,L>::print(FILE*) const { + // pure virtual +} + +template <class C, unsigned L> +void IfChunk<C,L>::xmlize(FILE*) const { + // pure virtual +} + +/* + * + * vect : implements variable-length vectors + * + */ + +template <typename T> +IfVector<T>::IfVector(const int length) { + m_length = length; + m_data = new T[m_length]; +} + +template <typename T> +IfVector<T>::IfVector(const IfVector<T>& vect) { + m_length = vect.m_length; + m_data = new T[m_length]; + for(int i = 0; i < m_length; i++) + m_data[i] = vect.m_data[i]; +} + +template <typename T> +IfVector<T>::~IfVector() { + delete[] m_data; +} + +template <typename T> +int IfVector<T>::find(const T t) const { + int pos = -1; + for(int i = 0; i < m_length && pos == -1; i++) + if (m_data[i] == t) + pos = i; + return pos; +} + +template <typename T> +void IfVector<T>::insert(const int k, const T t) { + if (0 <= k && k <= m_length) { + T* data = m_data; + m_data = new T[++m_length]; + for(int i = 0, j = 0; i < m_length; i++) + m_data[i] = (i == k) ? t : data[j++]; + delete[] data; + } +} + +template <typename T> +void IfVector<T>::remove(const int k) { + if (0 <= k && k < m_length) { + T* data = m_data; + m_data = new T[--m_length]; + for(int i = 0, j = 0; i < m_length; i++, j++) { + if (j == k) j++; + m_data[i] = data[j]; + } + delete[] data; + } +} + +template <typename T> +int IfVector<T>::compare(const IfVector<T>* vect) const { + int cmp = m_length - vect->m_length; + for(int i = 0; i < m_length && !cmp; i++) + cmp = (int) m_data[i] - (int) vect->m_data[i]; + return cmp; +} + +template <typename T> +unsigned long IfVector<T>::hash(const unsigned long base) const { + unsigned long key = 0; + for(int i = 0; i < m_length; i++) + key += ((unsigned long) m_data[i]) << (i % 17); + return key % base; +} + +template <typename T> +IfVector<T>* IfVector<T>::copy() const { + return new IfVector<T>(*this); +} + +template <typename T> +void IfVector<T>::print(FILE* file) const { +} + +template <typename T> +void IfVector<T>::printXML(std::ostream& buf) const { +} + +template <typename T> +void IfVector<T>::copy(const IfVector<T>* vect) { + if (m_length != vect->m_length) { + delete[] m_data; + m_length = vect->m_length; + m_data = new T[m_length]; + } + for(int i = 0; i < m_length; i++) + m_data[i] = vect->m_data[i]; +} + +/* + * + * linked list : implement double-linked lists + * + */ + +template <class C> +IfLinkedList<C>::IfLinkedList() { + m_first = NULL; + m_last = NULL; +} + +template <class C> +IfLinkedList<C>::~IfLinkedList() { + purge(); +} + +template <class C> +void IfLinkedList<C>::insert(const C* object, Node* next) { + Node* node = new Node; + node->m_object = (C*) object; + node->m_prev = node->m_next = NULL; + if (next == NULL) + next = m_first; + if (next) { + node->m_prev = next->m_prev; + node->m_next = next; + next->m_prev = node; + if (node->m_prev != NULL) + node->m_prev->m_next = node; + else + m_first = node; + } + else + m_first = m_last = node; +} + +template <class C> +void IfLinkedList<C>::append(const C* object, Node* prev) { + Node* node = new Node; + node->m_object = (C*) object; + node->m_prev = node->m_next = NULL; + if (prev == NULL) + prev = m_last; + if (prev) { + node->m_next = prev->m_next; + node->m_prev = prev; + prev->m_next = node; + if (node->m_next != NULL) + node->m_next->m_prev = node; + else + m_last = node; + } + else + m_first = m_last = node; +} + +template <class C> +void IfLinkedList<C>::remove(Node* node) { + if (node->m_next) + node->m_next->m_prev = node->m_prev; + else + m_last = node->m_prev; + if (node->m_prev) + node->m_prev->m_next = node->m_next; + else + m_first = node->m_next; + delete node->m_object; + delete node; +} + +template <class C> +void IfLinkedList<C>::purge() { + for(Node* node = m_first; node != NULL; + node = m_first) { + m_first = node->m_next; + delete node->m_object; + delete node; + } + m_last = NULL; +} + +/* + * + * heap : implements dynamic heaps + * + */ + +// warnings +// - object indexing must start at 1, not at 0 +// - count denotes here the last used position + +template <class C> +IfHeap<C>::IfHeap() { + m_length = 4; + m_objects = (C**) malloc(sizeof(C*) * m_length); + m_count = 0; +} + +template <class C> +IfHeap<C>::~IfHeap() { + free(m_objects); +} + +template <class C> +C* IfHeap<C>::get() { + if (m_count == 0) + return NULL; + + C* top = m_objects[1]; + m_objects[1] = m_objects[m_count--]; + + // balance + for(int j = 1; j <= m_count; ) { + int i = j * 2; + if (i > m_count) + break; + if (i + 1 <= m_count && + m_objects[i+1]->getPriority() > m_objects[i]->getPriority()) + i = i + 1; + if (m_objects[j]->getPriority() >= m_objects[i]->getPriority()) + break; + + C* tmp = m_objects[j]; + m_objects[j] = m_objects[i]; + m_objects[i] = tmp; + + j = i; + } + + return top; +} + +template <class C> +void IfHeap<C>::put(const C* object) { + if (m_count == m_length - 1) { + m_length += m_length; + m_objects = (C**) realloc(m_objects, sizeof(C*) * m_length); + } + + m_objects[++m_count] = (C*) object; + + // balance + for(int i = m_count; i > 1;) { + int j = i / 2; + + if (m_objects[j]->getPriority() >= m_objects[i]->getPriority()) + break; + + C* tmp = m_objects[j]; + m_objects[j] = m_objects[i]; + m_objects[i] = tmp; + + i = j; + } +} + +/* + * + * bit vect : implements fixed-length bitvectors + * + */ + +template <unsigned L> +IfBitVector<L>::IfBitVector() { + for(unsigned k = 0; k < L; k++) + m_data[k] = 0; +} + +template <unsigned L> +IfBitVector<L>::IfBitVector(const IfBitVector<L>& bvector) { + for(unsigned k = 0; k < L; k++) + m_data[k] = bvector.m_data[k]; +} + +template <unsigned L> +IfBitVector<L>::~IfBitVector() { +} + +template <unsigned L> +int IfBitVector<L>::in(const int idx) const { + if (0<=idx && idx<(int)L*8) + return (m_data[idx/8]<<(idx%8))&128; + else + return 0; +} + +template <unsigned L> +void IfBitVector<L>::set(const int idx) { + if (0<=idx && idx<(int)L*8) + m_data[idx/8] |= (128 >> (idx%8)); +} + +template <unsigned L> +void IfBitVector<L>::reset(const int idx) { + if (0<=idx && idx<(int)L*8) + m_data[idx/8] &= ~(128 >> (idx%8)); +} + +template <unsigned L> +unsigned IfBitVector<L>::cardinal() const { + unsigned card = 0; + for(unsigned k = 0; k < L; k++) + for(unsigned char c = m_data[k]; c; c <<= 1) + if (c & 128) card++; + return card; +} + +template <unsigned L> +int IfBitVector<L>::ord(const int idx) const { + int ord = -1; + if (in(idx)) { + ord = 0; + for(int k = 0; k < idx/8; k++) + for(unsigned char c = m_data[k]; c; c <<= 1) + if (c & 128) ord++; + for(int l = 0; l < idx%8; l++) { + unsigned char c = m_data[idx/8 + 1]; + if ((c << l) & 128) ord++; + } + } + return ord; +} + +template <unsigned L> +int IfBitVector<L>::first() const { + int idx = -1; + for(unsigned k = 0; k < L; k++) + if (m_data[k] != 255) { + idx = k*8; + for(unsigned char c = m_data[k]; c & 128; c <<= 1) + idx++; + break; + } + return idx; +} + +template <unsigned L> +int IfBitVector<L>::last() const { + int idx = -1; + for(int k = L - 1; k >= 0; k--) + if (m_data[k] != 0) { + idx = k*8 + 7; + for(unsigned char c = m_data[k]; !(c & 1); c >>= 1) + idx--; + break; + } + return idx; +} + +template <unsigned L> +void IfBitVector<L>::copy(const IfBitVector<L>* bvector) { + for(unsigned k = 0; k < L; k++) + m_data[k] = bvector->m_data[k]; +} + +template <unsigned L> +int IfBitVector<L>::compare(const IfBitVector<L>* bvector) const { + int cmp = 0; + for(unsigned k = 0; k < L && !cmp; k++) + cmp = m_data[k] - bvector->m_data[k]; + return cmp; +} + +template <unsigned L> +IfBitVector<L>* IfBitVector<L>::copy() const { + return new IfBitVector<L>(*this); +} + +template <unsigned L> +unsigned long IfBitVector<L>::hash(const unsigned long base) const { + unsigned long key = 0; + for(unsigned k = 0; k < L; k++) + key += m_data[k] << (3 * (k % 6)); + return key % base; +} + +template <unsigned L> +void IfBitVector<L>::print(FILE* file) const { + for(unsigned k = 0; k < L; k++) + fprintf(file, "%x", m_data[k]); +} + +template <unsigned L> +void IfBitVector<L>::printXML(std::ostream& buf) const { + buf << "<IfBitVector>\n"; + for(unsigned k = 0; k < L; k++) + buf << m_data[k]; + buf << "</IfBitVector>\n"; +} + diff --git a/src/simulator/table.h b/src/simulator/table.h new file mode 100644 index 0000000000000000000000000000000000000000..7aeee649cf2f517448bedafe69826a98b656e1a3 --- /dev/null +++ b/src/simulator/table.h @@ -0,0 +1,221 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * table : defines abstract tables + * + */ + +template <class C> +class IfTable { + + public: + IfTable(const char* = NULL); + virtual ~IfTable(); + + public: + inline unsigned getCount() const + { return m_count; } + + public: + virtual void purge(); + virtual C* store(const C* object); + virtual void remove(const C* object); + virtual void status(FILE* = stderr) const; + virtual void print(FILE* = stderr) const; + + protected: + const char* m_name; + unsigned long m_count; + +}; + +/* + * + * hash_table : defines hash collision list tables + * + */ + +#define HASHBLOCKSIZE 4 + +#define HASHTABLECOLS 32 + +template <class C> +class IfHashTable : public IfTable<C> { + + public: + IfHashTable(const char* = NULL); + virtual ~IfHashTable(); + + public: + virtual void purge(); + virtual C* store(const C* object); + virtual void remove(const C* object); + virtual void status(FILE* = stderr) const; + virtual void print(FILE* = stderr) const; + + protected: + void resize(); + + protected: + struct Block : public IfChunk<C,HASHBLOCKSIZE> { + Block* m_next; + inline int isFull() const + { return this->getAt(HASHBLOCKSIZE-1) != NULL; } + }; + + protected: + unsigned long m_size; + Block* *m_blocks; + +}; + +/* + * + * SplayTree : defines binary splay trees + * + */ + +template <class C> +class IfSplayTree : public IfTable<C> { + + public: + IfSplayTree(const char* = NULL); + virtual ~IfSplayTree(); + + public: + virtual void purge(); + virtual C* store(const C*); + virtual void status(FILE* = stderr) const; + virtual void print(FILE* = stderr) const; + + protected: + struct Node { + C* object; + Node* left; + Node* right; + }; + + protected: + void purge(Node*); + void splay(const C*); + void print(FILE*, Node*, int) const; + + protected: + Node* m_root; + +}; + +/* + * + * If23Tree : defines {2,3} balanced trees + * + */ + +#ifdef BLAH + +template <class C> +class If23Tree : public IfTable<C> { + + public: + If23Tree(const char* = NULL); + virtual ~If23Tree(); + + public: + virtual void purge(); + virtual C* store(const C*); + virtual void status(FILE* = stderr) const; + virtual void print(FILE* = stderr) const; + + protected: + enum NodeType { + UNARY_LEAF = 0, BINARY_LEAF, BINARY_NODE, TERNARY_NODE }; + struct Node { + NodeType tp; + Node(NodeType t) + :tp(t) {} + }; + struct UnaryLeaf : public Node { + C *k1; + UnaryLeaf(C* v1) + : Node( UNARY_LEAF ), k1(v1) {} + }; + struct BinaryLeaf : public Node { + C *k1, *k2; + BinaryLeaf(C* v1, C* v2) + : Node( BINARY_LEAF ), k1(v1), k2(v2) {} + }; + struct BinaryNode : public Node { + C *k1; + Node *l, *r; + BinaryNode(C* v1, Node* x, Node* y) + : Node( BINARY_NODE), k1(v1), l(x), r(y) {} + }; + struct TernaryNode : public Node { + C *k1, *k2; + Node *l, *m, *r; + TernaryNode(C* v1, C* v2, Node* x, Node* y, Node* z) + : Node( TERNARY_NODE), k1(v1), k2(v2), l(x), m(y), r(z) {} + }; + + protected: + Node* insert( Node* n, const C* k ); + Node* insert( UnaryLeaf* n, const C* k ); + Node* insert( BinaryLeaf* n, const C* k ); + Node* insert( BinaryNode* n, const C* k ); + Node* insert( TernaryNode* n, const C* k ); + + void purge( Node* n ); + void purge( UnaryLeaf* n ); + void purge( BinaryLeaf* n ); + void purge( BinaryNode* n ); + void purge( TernaryNode* n ); + + protected: + Node* m_root; + + C* m_key; + BinaryNode m_split; + +}; + +#endif + diff --git a/src/simulator/table.i b/src/simulator/table.i new file mode 100644 index 0000000000000000000000000000000000000000..f1e32f17780890141abcec13d78bacea6e2d6780 --- /dev/null +++ b/src/simulator/table.i @@ -0,0 +1,643 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * Table : implements abstract table + * + */ + +template <class C> +IfTable<C>::IfTable(const char* name) { + m_name = name; + m_count = 0; +} + +template <class C> +IfTable<C>::~IfTable() { +} + +template <class C> +void IfTable<C>::purge() { + // abstract +} + +template <class C> +C* IfTable<C>::store(const C* object) { + // abstract + return NULL; +} + +template <class C> +void IfTable<C>::remove(const C* object) { + // abstract +} + +template <class C> +void IfTable<C>::status(FILE* file) const { + // abstract +} + +template <class C> +void IfTable<C>::print(FILE* file) const { + // abstract +} + +/* + * + * HashTable : implements hash collision list table + * + */ + +template <class C> +IfHashTable<C>::IfHashTable(const char* name) + : IfTable<C>(name) { + m_size = 13; + m_blocks = new Block*[m_size]; + for(unsigned long i = 0; i < m_size; i++) + m_blocks[i] = NULL; +} + +template <class C> +IfHashTable<C>::~IfHashTable() { + status(stderr); + purge(); +} + +template <class C> +void IfHashTable<C>::purge() { + for(unsigned long i = 0; i < m_size; i++) { + Block* block = m_blocks[i]; + while (block != NULL) { + Block* next = block->m_next; + for(unsigned long j = 0; j < HASHBLOCKSIZE; j++) + if (block->getAt(j) != NULL) + delete block->getAt(j); + delete block; + block = next; + } + } + delete[] m_blocks; +} + +template <class C> +C* IfHashTable<C>::store(const C* object) { + C* store = NULL; + unsigned long k = object->hash(m_size); + Block* block = m_blocks[k]; + while (block != NULL) { + for(unsigned long i = 0; i < HASHBLOCKSIZE; i++) + if (block->getAt(i) && + block->getAt(i)->compare(object) == 0) { + store = block->getAt(i); + break; + } + block = store ? NULL : block->m_next; + } + if (store == NULL) { + this->m_count++; + store = (C*) object->copy(); +/* left this for future reference : + if(store->hash(m_size) != k) { + printf("simulator internal warning: non-optimal hashing.\n"); + object->print(stdout); + } + */ + block = m_blocks[k]; + if (block == NULL || block->isFull()) { + Block* b = new Block; + b->m_next = block; + block = m_blocks[k] = b; + } + for(unsigned long i = 0; i < HASHBLOCKSIZE; i++) + if (block->getAt(i) == NULL) { + block->setAt(i, store); + break; + } + if (this->m_count / m_size > HASHTABLECOLS) + resize(); + } + return store; +} + +template <class C> +void IfHashTable<C>::remove(const C* object) { + + unsigned long k = object->hash(m_size); + + Block *bo = NULL; + unsigned long io = 0; + + // locate the object in the collision list + for(Block* block = m_blocks[k]; block != NULL && bo == NULL; + block = block->m_next) + for(unsigned long i = 0; i < HASHBLOCKSIZE; i++) + if (block->getAt(i) == object) { + bo = block; io = i; + break; + } + + if (bo == NULL) + return; + + // locate the last object in the collision list + Block *bl = m_blocks[k]; + unsigned long il = HASHBLOCKSIZE - 1; + + while (bl->m_next != NULL && + bl->getAt(0) != NULL) + bl = bl->m_next; + while (bl->getAt(il) == NULL) + il--; + + // swap, then delete object + + bo->setAt(io, bl->getAt(il)); + bl->setAt(il, NULL); + + delete object; + + this->m_count--; +} + +template <class C> +void IfHashTable<C>::status(FILE* file) const { + unsigned long min = 1000000, max = 0, bc = 0; + for(unsigned long i = 0; i < m_size; i++) { + unsigned long length = 0; + for(Block* block = m_blocks[i]; block; + block = block->m_next) + length ++; + if (min > length) min = length; + if (max < length) max = length; + bc += length; + } + fprintf(file, "%8s table : %7ld items %6ld/entry %2ld/min %2ld/max %5.2f/avg\n", + this->m_name, this->m_count, m_size, min * HASHBLOCKSIZE, max * HASHBLOCKSIZE, + (float) this->m_count / (float) m_size); +} + +template <class C> +void IfHashTable<C>::print(FILE* file) const { + for(unsigned long i = 0; i < m_size; i++) { + fprintf(file, "\nentry %lu:\n", i); + for(Block* block = m_blocks[i]; block; + block = block->m_next) { + for(int j = 0; j < HASHBLOCKSIZE && block->getAt(j); j++) + { block->getAt(j)->print(file); fprintf(file, "\n"); } + } + } +} + +template <class C> +void IfHashTable<C>::resize() { + unsigned long size = if_nextprime(2 * m_size + 1); + unsigned long i; + + Block* *blocks = new Block* [size]; + for(i = 0; i < size; i++) + blocks[i] = NULL; + for(i = 0; i < m_size; i++) { + Block* block = m_blocks[i]; + while (block != NULL) { + Block* next = block->m_next; + for(unsigned long j = 0; j < HASHBLOCKSIZE; j++) + if (block->getAt(j) != NULL) { + unsigned long k = block->getAt(j)->hash(size); + if (blocks[k] == NULL || blocks[k]->isFull()) { + Block* b = new Block; + b->m_next = blocks[k]; + blocks[k] = b; + } + for(unsigned long l = 0; l < HASHBLOCKSIZE; l++) + if (blocks[k]->getAt(l) == NULL) { + blocks[k]->setAt(l, block->getAt(j)); + break; + } + } + delete block; + block = next; + } + } + delete[] m_blocks; + m_blocks = blocks; + m_size = size; +} + + +/* + * + * SplayTree : implements splay trees + * + */ + +template <class C> +IfSplayTree<C>::IfSplayTree(const char* name) + : IfTable<C>(name) { + m_root = NULL; +} + +template <class C> +IfSplayTree<C>::~IfSplayTree() { + status(stderr); + purge(); +} + +template <class C> +void IfSplayTree<C>::purge() { + if (m_root) purge(m_root); +} + +template <class C> +C* IfSplayTree<C>::store(const C* object) { + + if (m_root == NULL) { + m_root = new Node; + m_root->object = (C*) object->copy(); + m_root->left = m_root->right = NULL; + this->m_count = 1; + } + + else { + int cmp = 0; + splay(object); + cmp = object->compare(m_root->object); + if (cmp < 0) { + Node* n = new Node; + n->object = (C*) object->copy(); + n->left = m_root->left; + n->right = m_root; + m_root->left = NULL; + m_root = n; + this->m_count++; + } + else if (cmp > 0) { + Node* n = new Node; + n->object = (C*) object->copy(); + n->right = m_root->right; + n->left = m_root; + m_root->right = NULL; + m_root = n; + this->m_count++; + } + } + + return m_root->object; +} + +template <class C> +void IfSplayTree<C>::status(FILE* file) const { + fprintf(file, "%8s table : %7d items\n", + this->m_name, this->m_count); +} + +template <class C> +void IfSplayTree<C>::print(FILE* file) const { + fprintf(file, "%s table :\n", this->m_name); + print(file, m_root, 0); +} + +template <class C> +void IfSplayTree<C>::purge(Node* t) { + if (t->left) purge(t->left); + if (t->right) purge(t->right); + delete t->object; + delete t; +} + +template <class C> +void IfSplayTree<C>::splay(const C* object) { + // simple top down splay, not requiring object to be in the tree + Node N, *l, *r, *y, *t = m_root; + int cmp = 0; + + N.left = N.right = NULL; + l = r = &N; + + for (;;) { + cmp = object->compare(t->object); + if (cmp < 0) { + if (t->left == NULL) break; + cmp = object->compare(t->left->object); + if (cmp < 0) { + y = t->left; // rotate right + t->left = y->right; + y->right = t; + t = y; + if (t->left == NULL) break; + } + r->left = t; // link right + r = t; + t = t->left; + } + else if (cmp > 0) { + if (t->right == NULL) break; + cmp = object->compare(t->right->object); + if (cmp > 0) { + y = t->right; // rotate left + t->right = y->left; + y->left = t; + t = y; + if (t->right == NULL) break; + } + l->right = t; // link left + l = t; + t = t->right; + } + else { + break; + } + } + + l->right = t->left; // assemble + r->left = t->right; + t->left = N.right; + t->right = N.left; + + m_root = t; +} + +template <class C> +void IfSplayTree<C>::print(FILE* file, Node* t, int depth) const { + if (t) + print(file, t->left, depth + 1); + for(int i = 0; i < depth; i++) + fprintf(file, " "); + if (t) + t->object->print(file); + else + fprintf(file, "-"); + fprintf(file, "\n"); + if (t) + print(file, t->right, depth + 1); +} + +/* + * + * B23Tree : implements {2,3} balanced trees + * + */ + +#ifdef IF23TREE + +template <class C> +If23Tree<C>::If23Tree(const char* name) + : IfTable<C>(name), m_root(NULL), m_key(NULL), m_split(NULL, NULL, NULL) { +} + +template <class C> +If23Tree<C>::~If23Tree() { + status(stderr); + purge(); +} + +template <class C> +void If23Tree<C>::purge() { + if (m_root) + purge( m_root ); + m_root = NULL; +} + +template <class C> +C* If23Tree<C>::store( const C* k ) { + + if (m_root == NULL) { + m_key = (C*) k->copy(); + m_root = new UnaryLeaf( m_key ); + this->m_count ++; + + } else { + m_root = insert( m_root, k ); + if ( m_root == NULL ) + m_root = new BinaryNode( m_split.k1, m_split.l, m_split.r ); + } + + return m_key; +} + +template <class C> +void If23Tree<C>::status(FILE* file) const { + fprintf(file, "%8s table : %7d items\n", + this->m_name, this->m_count); +} + +template <class C> +void If23Tree<C>::print(FILE* file) const { + // not yet implemented +} + +template <class C> +If23Tree<C>::Node* If23Tree<C>::insert( Node* n, const C* k ) { + switch ( n->tp ) { + case UNARY_LEAF : return insert( (UnaryLeaf*) n, k ); + case BINARY_LEAF : return insert( (BinaryLeaf*) n, k ); + case BINARY_NODE : return insert( (BinaryNode*) n, k ); + case TERNARY_NODE : return insert( (TernaryNode*) n, k); + } + return NULL; +} + +template <class C> +If23Tree<C>::Node* If23Tree<C>::insert( UnaryLeaf* n, const C* k) { + Node* result = n; + int c1 = k->compare( n->k1 ); + + if ( c1 == 0 ) + m_key = n->k1; + + else { + this->m_count++; + m_key = (C*) k->copy(); + if (c1 < 0) + result = new BinaryLeaf( m_key, n->k1); + else + result = new BinaryLeaf( n->k1, m_key ); + delete n; + } + + return result; +} + +template <class C> +If23Tree<C>::Node* If23Tree<C>::insert( BinaryLeaf* n, const C* k) { + Node* result = n; + int c1 = k->compare( n->k1 ); + int c2 = k->compare( n->k2 ); + + if (c1 == 0) + m_key = n->k1; + + else if ( c2 == 0 ) + m_key = n->k2; + + else { + this->m_count++; + m_key = (C*) k->copy(); + // split initialize + if (c1 < 0) { + m_split.k1 = n->k1; + m_split.l = new UnaryLeaf( m_key ); + m_split.r = new UnaryLeaf( n->k2 ); + } else if ( c2 < 0) { + m_split.k1 = m_key; + m_split.l = new UnaryLeaf( n->k1 ); + m_split.r = new UnaryLeaf( n->k2 ); + } else { + m_split.k1 = n->k2; + m_split.l = new UnaryLeaf( n->k1 ); + m_split.r = new UnaryLeaf( m_key ); + } + delete n; + result = NULL; + } + + return result; +} + +template <class C> +If23Tree<C>::Node* If23Tree<C>::insert( BinaryNode* n, const C* k) { + Node* result = n; + int c1 = k->compare( n->k1 ); + + if (c1 == 0) { + m_key = n->k1; + + } else { + Node* t = NULL; + + if ( c1 < 0 ) { + t = n->l = insert (n->l, k); + if ( t == NULL) // split on left branch, absortion + result = new TernaryNode( m_split.k1, n->k1, + m_split.l, m_split.r, n->r); + } + else { + t = n->r = insert (n->r, k); + if ( t == NULL ) // split on right branch, absortion + result = new TernaryNode( n->k1, m_split.k1, + n->l, m_split.l, m_split.r); + } + + if ( t == NULL ) + delete n; + } + + return result; +} + +template <class C> +If23Tree<C>::Node* If23Tree<C>::insert( TernaryNode* n, const C* k) { + Node* result = n; + int c1 = k->compare( n->k1 ); + int c2 = k->compare( n->k2 ); + + if ( c1 == 0 ) + m_key = n->k1; + + else if ( c2 == 0 ) + m_key = n->k2; + + else { + Node* t = NULL; + + if (c1 < 0) { + t = n->l = insert (n->l, k); + if ( t == NULL ) { // split on left branch, propagate + m_split.l = new BinaryNode( m_split.k1, m_split.l, m_split.r); + m_split.k1 = n->k1; + m_split.r = new BinaryNode( n->k2, n->m, n->r); + } + } else if ( c2 < 0 ) { + t = n->m = insert (n->m, k); + if ( t == NULL ) { // split on middle branch, propagate + m_split.l = new BinaryNode( n->k1, n->l, m_split.l); + m_split.r = new BinaryNode( n->k2, m_split.r, n->r); + } + } else { + t = n->r = insert (n->r, k); + if ( t == NULL ) { // split on right branch, propagate + m_split.r = new BinaryNode( m_split.k1, m_split.l, m_split.r); + m_split.k1 = n->k2; + m_split.l = new BinaryNode ( n->k1, n->l, n->m); + } + } + + if ( t == NULL ) { // split + delete n; + result = NULL; + } + } + + return result; +} + +template <class C> +void If23Tree<C>::purge( Node* n) { + switch ( n->tp ) { + case UNARY_LEAF : purge( (UnaryLeaf*) n); break; + case BINARY_LEAF : purge( (BinaryLeaf*) n); break; + case BINARY_NODE : purge( (BinaryNode*) n); break; + case TERNARY_NODE : purge( (TernaryNode*) n); break; + } +} + +template <class C> +void If23Tree<C>::purge( UnaryLeaf* n ) { + delete n->k1; delete n; +} + +template <class C> +void If23Tree<C>::purge( BinaryLeaf* n ) { + delete n->k1; delete n->k2; delete n; +} + +template <class C> +void If23Tree<C>::purge( BinaryNode* n ) { + purge( n->l ); purge( n->r ); + delete n->k1; delete n; +} + +template <class C> +void If23Tree<C>::purge( TernaryNode* n ) { + purge( n->l ); purge(n->m); purge( n->r ); + delete n->k1; delete n->k2; delete n; +} + +#endif diff --git a/src/simulator/xtime.C b/src/simulator/xtime.C new file mode 100644 index 0000000000000000000000000000000000000000..b9b1021e12e0d24a47a7db8209bf198302667ae9 --- /dev/null +++ b/src/simulator/xtime.C @@ -0,0 +1,480 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +#include "simulator.h" + +/* + * + * time : implements abstract time + * + */ + +const char* IfTime::NAME = IfInstance::PROCNAME[PROCMAXNUM-1] = "time"; + +if_pid_type IfTime::ALLOCATOR[CLKMAXNUM]; + +IfTime::IfTime() + : IfInstance(if_pid_mk(PROCMAXNUM-1,0)), m_clocks(1) { + m_clocks.setAt(0,0); +} + +IfTime::IfTime(const IfTime& time) + : IfInstance(time), m_clocks(time.m_clocks) { +} + +IfTime::~IfTime() { +} + +int IfTime::active(const if_clock_type clock) const { + return m_clocks.find(clock) >= 0 ? 1 : 0; +} + +int IfTime::timeval(const if_clock_type clock) const { + // abstract + return -1; +} + +int IfTime::guard(Constraint*, const if_deadline) { + // abstract + return 0; +} + +void IfTime::set(if_clock_type*, const if_time_value, const if_pid_type) { + // abstract +} + +void IfTime::resetClock(if_clock_type*) { + // abstract +} + +int IfTime::include(const IfTime*) const { + // abstract + return 0; +} + +int IfTime::allocate(if_clock_type* clock, + const if_pid_type pid) { + int i = 0, k = 0; + for(;;) { + if (ALLOCATOR[k] != 0 && ALLOCATOR[k] != pid) + { k++; continue; } + if (i == dimension() || k < m_clocks.getAt(i)) + break; + if (k == m_clocks.getAt(i)) + { k++; i++; continue; } + if (k > m_clocks.getAt(i)) + { i++; continue; } + } + assert(k < CLKMAXNUM); + ALLOCATOR[k] = pid; + *clock = k; + return i; +} + +/* + * + * discrete time : implements discrete / discrete / enumerative time + * + */ + +int IfDiscreteTime::DELTA = -1; + +IfDiscreteTime::IfDiscreteTime() + : IfTime(), m_values(1) { + m_values.setAt(0,0); +} + +IfDiscreteTime::IfDiscreteTime(const IfDiscreteTime& time) + : IfTime(time), m_values(time.m_values) { +} + +IfDiscreteTime::~IfDiscreteTime() { +} + +int IfDiscreteTime::timeval(const if_clock_type clock) const { + if_time_value value = -1; + int k = m_clocks.find(clock); + if (k > 0) + value = m_values.getAt(k); + return value; +} + +int IfDiscreteTime::guard(Constraint* constraint, + const if_deadline deadline) { + int enabled = 1; + int delta = -1; + + for(int j = 0; !constraint[j].isEmpty(); j++) { + + constraint[j].active = 0; + constraint[j].delta = 0; + + for(int i = 0; i < dimension(); i++) { + if (m_clocks.getAt(i) == constraint[j].x) { + constraint[j].active += 1; + constraint[j].delta += m_values.getAt(i); + } + if (m_clocks.getAt(i) == constraint[j].y) { + constraint[j].active += 2; + constraint[j].delta -= m_values.getAt(i); + } + if (constraint[j].active == 3) + break; + } + + constraint[j].delta = + constraint[j].k - 2 * constraint[j].delta; + + enabled &= (constraint[j].active == 3 && + constraint[j].delta > 0) ? 1 : 0; + } + + if (enabled) { + int j; + + switch (deadline) { + case EAGER: delta = 0; break; + case DELAYABLE: delta = 1; + for(j = 0; !constraint[j].isEmpty(); j++) + if (constraint[j].x && !constraint[j].y) + if (constraint[j].delta - 2 <= 0) { + delta = 0; + break; + } + break; + case LAZY: delta = 1; break; + } + } + else { + for(int j = 0; !constraint[j].isEmpty(); j++) { + if (constraint[j].active != 3 || + (constraint[j].delta <= 0 && constraint[j].x)) { + delta = -1; + break; + } + if (constraint[j].delta <= 0) + if (delta == -1 || delta < -constraint[j].delta) + delta = -constraint[j].delta; + } + if (delta > 0) + delta = delta / 2 + 1; + } + + if (delta >= 0 && (DELTA == -1 || DELTA > delta)) + DELTA = delta; + + return enabled; +} + + +void IfDiscreteTime::set(if_clock_type *clock, + const if_time_value value, + const if_pid_type pid) { + int k = m_clocks.find(*clock); + if (k < 0) { + k = allocate(clock, pid); + m_clocks.insert(k, *clock); + m_values.insert(k, 0); + } + m_values.setAt(k, value); +} + +void IfDiscreteTime::resetClock(if_clock_type* clock) { + int k = m_clocks.find(*clock); + if (k >= 0) { + m_clocks.remove(k); + m_values.remove(k); + } + *clock = -1; +} + +int IfDiscreteTime::compare(const IfInstance* instance) const { + IfDiscreteTime* time = (IfDiscreteTime*) instance; + int cmp = IfInstance::compare(instance); + if (cmp == 0) cmp = m_clocks.compare(&time->m_clocks); + if (cmp == 0) cmp = m_values.compare(&time->m_values); + return cmp; +} + +long unsigned IfDiscreteTime::hash(const unsigned long base) const { + unsigned long key = 0; + for(int i = 0; i < dimension(); i++) { + unsigned value = (unsigned) m_values.getAt(i); + unsigned clock = m_clocks.getAt(i); + key += value ? value << (clock % 17) : clock << (i % 17); + } + return key % base; +} + +IfInstance* IfDiscreteTime::copy() const { + return new IfDiscreteTime(*this); +} + +void IfDiscreteTime::print(FILE* file) const { + IfInstance::print(file); + fprintf(file, "\n @run\t\t"); + for(int i = 0; i < dimension(); i++) + fprintf(file, "%d/%d ", m_values.getAt(i), m_clocks.getAt(i)); +} + +void IfDiscreteTime::printXML(std::ostream& buf) const { + buf << "<IfDiscreteTime>\n"; + //IfInstance::printXML(buf); + for(int i = 0; i < dimension(); i++) { + buf << "<clockvalue clockid='" << m_clocks.getAt(i) << "' value='" << m_values.getAt(i) << "' />\n"; + } + buf << "</IfDiscreteTime>\n"; +} + +void IfDiscreteTime::iterate(IfIterator* iterator) { + + if (DELTA != 0) { + + char delta[32] = "oo"; + if (DELTA != -1) + sprintf(delta, "%d", DELTA); + + iterator->trace(IfEvent::TICK, m_pid, delta); + + if (DELTA != -1) + for(int i = 1; i < dimension(); i++) + m_values.setAt(i, m_values.getAt(i) + DELTA); + + iterator->step(); + + } + + DELTA = -1; // restart +} + +void IfDiscreteTime::copy(const IfInstance* instance) { + IfDiscreteTime* time = (IfDiscreteTime*) instance; + m_clocks.copy(&time->m_clocks); + m_values.copy(&time->m_values); +} + +int IfDiscreteTime::include(const IfTime* time) const { + return compare(time) == 0; +} + +/* + * + * continuous time : continuous / dense / symbolic time + * + *******************************************************/ + +static int zone_module_initialzed = 0; + +if_type_zone_list IfDbmTime::m_restrictions; +if_type_zone_list IfDbmTime::m_split; + + +IfDbmTime::IfDbmTime() + : IfTime() { + if(!zone_module_initialzed) { + zone_module_initialzed = 1; + if_init_zone_module(); + if_init_tpc(&m_restrictions); + if_init_tpc(&m_split); + } + m_dbm = if_universal_zone(); +} + +IfDbmTime::IfDbmTime(const IfDbmTime& time) + : IfTime(time) { + m_dbm = time.m_dbm; +} + +IfDbmTime::~IfDbmTime() { +} + +void IfDbmTime::restrictExtrapolationZone(int cmax) { + if(!zone_module_initialzed) { + zone_module_initialzed = 1; + if_init_zone_module(); + if_init_tpc(&m_restrictions); + if_init_tpc(&m_split); + } + if_restrict_extrapolation_zone(cmax); +} + +int IfDbmTime::timeval(const if_clock_type clock) const { + fprintf(stderr, "\nerror #3: timeval operator ignored!\n"); + return -1; +} + +int IfDbmTime::guard(Constraint* constraint, + const if_deadline deadline) { + int libdeadline; + + switch(deadline) { + case EAGER: libdeadline = 0; break; + case DELAYABLE: libdeadline = 1; break; + default : libdeadline = 2; + } + + if_type_zone guard = if_universal_zone(); + for(int j = 0; !constraint[j].isEmpty(); j++) { + if ( constraint[j].x == -1 || constraint[j].y == -1 ) + return 0; + if_type_zone c = if_clkcmp_zone(constraint[j].x, constraint[j].y, if_value_bound(constraint[j].k), if_sign_bound(constraint[j].k)); + guard = if_intersect_zone(guard, c); + } + + m_dbm = if_intersect_zone(m_dbm, guard); + + if(deadline != LAZY) if_guard_tpc(&m_restrictions, guard, libdeadline); + + /*!!!*/if (opt_use_priorities && !if_is_empty_zone(m_dbm)) if_guard_split(&m_split, guard); + + return !if_is_empty_zone(m_dbm); +} + + +void IfDbmTime::set(if_clock_type *clock, + const if_time_value value, + const if_pid_type pid) { + int k = m_clocks.find(*clock); + if (k < 0) { + k = allocate(clock, pid); + m_clocks.insert(k, *clock); + } + m_dbm = if_set_zone(m_dbm, *clock, value); +} + +void IfDbmTime::resetClock(if_clock_type* clock) { + int k = m_clocks.find(*clock); + if (k >= 0) { + m_clocks.remove(k); + m_dbm = if_exists_zone(m_dbm, *clock); + } + *clock = -1; +} + +void IfDbmTime::splitByPrio(IfIterator* iterator) { + if ( !opt_use_priorities ) + return; + + if(if_simple_is_universal_zone_list(m_split)) + return; + if(m_split == NULL) { + if_init_tpc(&m_split); + return; + } + + int i = 0; + char label[18]; + //iterator->record(); + for(if_type_zone_list lz = m_split; lz != NULL; lz = lz->next){ + iterator->restore(); + if_type_zone z = if_intersect_zone(m_dbm, lz->zone); + if (if_is_empty_zone(z)) + continue; + if_copy_zone(m_dbm, z); + sprintf(label,"split %d", ++i); + iterator->trace(IfEvent::TICK, m_pid, label); + iterator->step(); + } + //iterator->forget(); + if_clear_tpc(&m_split); if_init_tpc(&m_split); +} + +int IfDbmTime::compare(const IfInstance* instance) const { + IfDbmTime* time = (IfDbmTime*) instance; + int cmp = IfInstance::compare(instance); + if (cmp == 0) cmp = m_clocks.compare(&time->m_clocks); + if (cmp == 0) cmp = !(m_dbm == time->m_dbm); + return cmp; +} + +long unsigned IfDbmTime::hash(const unsigned long base) const { + return if_hash_zone(m_dbm, base); +} + +IfInstance* IfDbmTime::copy() const { + return new IfDbmTime(*this); +} + +void IfDbmTime::print(FILE* file) const { + IfInstance::print(file); + fprintf(file, "\n @run\t\t"); + if_print_zone(m_dbm, file); +} + +void IfDbmTime::printXML(std::ostream& buf) const { + buf << "<IfDbmTime value=\""; + char *c = this->string(); + buf << c; + buf << "\"/>\n"; +} + +void IfDbmTime::iterate(IfIterator* iterator) { + if( NULL != m_split ) if_clear_tpc(&m_split); + if_init_tpc(&m_split); + if(!m_restrictions) { + if_init_tpc(&m_restrictions); + return; + } + +// iterator->record(); + for(if_type_zone_list lz = m_restrictions; lz != NULL; lz = lz->next){ + iterator->restore(); + if_type_zone z = if_since_zone(m_dbm, lz->zone); + if (if_is_empty_zone(z)) + continue; + if_copy_zone(m_dbm, z); + iterator->trace(IfEvent::TICK, m_pid, ""); + iterator->step(); + } +// iterator->forget(); + if_clear_tpc(&m_restrictions); if_init_tpc(&m_restrictions); +} + +void IfDbmTime::copy(const IfInstance* instance) { + IfDbmTime* time = (IfDbmTime*) instance; + m_clocks.copy(&time->m_clocks); + m_dbm = time->m_dbm; +} + +int IfDbmTime::include(const IfTime* instance) const { + IfDbmTime* time = (IfDbmTime*) instance; + return if_include_zone(time->m_dbm, m_dbm); +} + diff --git a/src/simulator/xtime.h b/src/simulator/xtime.h new file mode 100644 index 0000000000000000000000000000000000000000..c121c5a8d1c93ae5137eafcab50db172d73fb7c4 --- /dev/null +++ b/src/simulator/xtime.h @@ -0,0 +1,194 @@ +/* + * + * IF-Toolset - Copyright (C) UGA - CNRS - G-INP + * + * by Marius - Iulian - Susanne - Laurent - Joseph + * Bozga - Ober - Graf - Mounier - Sifakis + * + * This software is a computer program whose purpose is to simulate, + * explore and model-check real-time systems represented using the IF - + * intermediate format - language. This software package contains + * sources, documentation, and examples. + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the + * CeCILL-B license as circulated by CEA, CNRS and INRIA at the following + * URL "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided + * only with a limited warranty and the software's author, the holder of + * the economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards + * their requirements in conditions enabling the security of their + * systems and/or data to be ensured and, more generally, to use and + * operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + * + */ + +/* + * + * basic type definitions + * + */ + +enum if_deadline { EAGER = 0, DELAYABLE, LAZY }; // deadlines + +typedef if_integer_type if_time_value; // clock values k + +typedef if_integer_type if_time_bound; // clock bounds # k + +/* + * + * time : defines abstract clock state + * + */ + +#define CLKMAXNUM 512 + +class IfTime : public IfInstance { + + public: + struct Constraint { // defines clock constraints x - y # k + if_clock_type x; + if_clock_type y; + if_time_bound k; + unsigned active; + int delta; + + inline int isEmpty() const + { return x == 0 && y == 0; } + }; + + public: + IfTime(); + IfTime(const IfTime&); + virtual ~IfTime(); + + public: + inline int dimension() const + { return m_clocks.getLength(); } + + public: + virtual int active(const if_clock_type) const; + virtual int timeval(const if_clock_type) const; + virtual int guard(Constraint*, const if_deadline); + virtual void set(if_clock_type*, const if_time_value, + const if_pid_type); + virtual void resetClock(if_clock_type*); + virtual void splitByPrio(IfIterator* iterator) {} + + public: + virtual int getPriority() const + { return -1; } + + public: + virtual int include(const IfTime*) const; + + public: + static const char* NAME; + + protected: + int allocate(if_clock_type*, const if_pid_type); + + protected: + IfVector<if_clock_type> m_clocks; + + private: + static if_pid_type ALLOCATOR[CLKMAXNUM]; + +}; + + +/* + * + * discrete_time : defines discrete / discrete / enumerative time + * + */ + +#include "ifzone.h" + +class IfDiscreteTime : public IfTime { + + public: + IfDiscreteTime(); + IfDiscreteTime(const IfDiscreteTime&); + virtual ~IfDiscreteTime(); + + public: + virtual int timeval(const if_clock_type) const; + virtual int guard(Constraint*, const if_deadline); + virtual void set(if_clock_type*, const if_time_value, + const if_pid_type); + virtual void resetClock(if_clock_type*); + + public: + virtual void iterate(IfIterator*); + virtual void copy(const IfInstance*); + + public: + virtual int include(const IfTime*) const; + + public: + DECLARE_STORABLE(IfInstance) + + protected: + IfVector<if_time_value> m_values; + + private: + static int DELTA; + +}; + +/* + * + * continuous_time : defines continuous / dense / symbolic time + * + */ + +class IfDbmTime : public IfTime { + + public: + IfDbmTime(); + IfDbmTime(const IfDbmTime&); + virtual ~IfDbmTime(); + + static void restrictExtrapolationZone(int cmax); + + public: + virtual int timeval(const if_clock_type) const; + virtual int guard(Constraint*, const if_deadline); + virtual void set(if_clock_type*, const if_time_value, + const if_pid_type); + virtual void resetClock(if_clock_type*); + + public: + virtual void splitByPrio(IfIterator* iterator); + virtual void iterate(IfIterator*); + virtual void copy(const IfInstance*); + virtual int include(const IfTime*) const; + + public: + DECLARE_STORABLE(IfInstance) + + protected: + if_type_zone m_dbm; + + private: + static if_type_zone_list m_restrictions; + static if_type_zone_list m_split; + +}; +