PK
u@ڭ, fr.supelec.modhelx/.project
fr.supelec.modhelx
fr.irisa.triskell.kermeta.kpm.kpmBuilder
fr.irisa.triskell.kermeta.KermetaNature
PK
u@wJ J = fr.supelec.modhelx/.settings/org.eclipse.core.resources.prefseclipse.preferences.version=1
encoding//metamodel/modhelx.ecorediag=UTF-8
PK
(w@H * fr.supelec.modhelx/metamodel/modhelx.ecore
PK
u@qST . fr.supelec.modhelx/metamodel/modhelx.ecorediag
PK C@ fr.supelec.modhelx/model/ PK PK
&@a! ! 9 fr.supelec.modhelx/src/kermeta/core/abstractSemantics.kmt/*
* $Id:$
* Creation : May 15, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* hardebolle
*/
package modhelx::core;
require kermeta
require "http://www.supelec.fr/modhelx/v1"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using modhelx::core
/*
* This file contains the abstract semantics of ModHel'X
* i.e. the abstract definition of all operations necessary to define the semantics of a model in ModHel'X
*
*/
/*** Model of the state of the model for execution : Tokens ***/
class Token {
// a token may have a value, which is given by the MoC according to which it is interpreted
operation getValue() : Object is abstract
operation setOwnerMoC(moc : ModelOfComputation) is abstract
}
aspect class Pin {
// pins are made to store and get tokens
operation addToken(token : Token) is abstract
operation getToken(remove : Boolean) : Token is abstract
operation getTokens() : Token [0..*] is abstract
operation hasToken() : Boolean is abstract
operation clearTokens() is abstract
}
/*** Snapshot/update triggering ***/
// objects allowing the triggering of an update on an observable entity
abstract class UpdateTrigger {
operation getEntityToUpdate() : ObservableEntity is abstract
operation setEntityToUpdate(o: ObservableEntity) is abstract
operation getTimeOfUpdate() : Integer is abstract
operation setTimeOfUpdate(t: Integer) is abstract
// prepare = provide all necessary information to the entity so that it can be updated
operation prepareToTrigger() is abstract
// trigger = basically update the entity to update (but may cover other things if necessary)
operation trigger() is abstract
}
// basic update triggers are snapshot requests made by blocks
class SnapshotRequest inherits UpdateTrigger {
}
/*** Abstract semantics for MoCs -- will be specialized ***/
aspect abstract class ModelOfComputation {
// operations for tokens
operation getTokenValue(t : Token) : Object is abstract
operation setTokenValue(t : Token, val : Object) is abstract
operation createToken(val : Object) : Token is abstract
// prep : done just after loading the model (e.g. type resolution...)
operation prep(s : BlockStructure) is abstract
// beginning of the simulation, done just before executing the model (pair with wrapup, done just after executing)
operation setup(s : BlockStructure) is abstract
// collect the initial requests for snapshots (for source blocks in particular)
operation collectInitialSnapshotRequests(s : BlockStructure, sr : Sequence) is abstract
// operations for computing the snapshot
operation startOfSnapshot(s : BlockStructure) is abstract
operation reset(s : BlockStructure) is abstract
operation schedule(s : BlockStructure) is abstract
operation update(s : BlockStructure) is abstract
operation propagate(s : BlockStructure) is abstract
operation canGoFurther(s : BlockStructure) : Boolean is abstract
operation validate(s : BlockStructure) : Boolean is abstract
operation endOfSnapshot(s : BlockStructure) is abstract
// collect snapshot requests for next snapshot
operation collectSnapshotRequests(s : BlockStructure, sr : Sequence) is abstract
// end of the simulation
operation wrapup(s : BlockStructure) is abstract
}
/*** Observable entities ***/
aspect abstract class ObservableEntity {
// operations for pins
operation addPin(name : String) : Pin is abstract
operation getPin(name : String) : Pin is abstract
// operations for execution
operation prep() is abstract
operation setup() is abstract
operation collectInitialSnapshotRequests(sr : Sequence) is abstract
operation startOfSnapshot() is abstract
operation reset() is abstract
operation update() is abstract // most important operation for an observable entity : it can be updated
operation validate() : Boolean is abstract
operation endOfSnapshot() is abstract
operation collectSnapshotRequests(sr : Sequence) is abstract
operation wrapup() is abstract
}
// Model inherits ObservableEntity
aspect class Model {
// operations necessary for hierarchical execution, delegated to the moc associated to the model
method prep() is do
self.moc.prep(self.structure)
end
method setup() is do
self.moc.setup(self.structure)
end
method collectInitialSnapshotRequests(sr : Sequence) is do
self.moc.collectInitialSnapshotRequests(self.structure, sr)
end
method startOfSnapshot() is do
self.moc.startOfSnapshot(self.structure)
end
method reset() is do
self.moc.reset(self.structure)
end
method update() is do
from var canGoFurther : Boolean init self.moc.canGoFurther(self.structure) until not canGoFurther
loop
self.moc.schedule(self.structure)
self.moc.update(self.structure)
self.moc.propagate(self.structure)
canGoFurther := self.moc.canGoFurther(self.structure)
end
end
method validate() : Boolean is do
result := self.moc.validate(self.structure)
end
method endOfSnapshot() is do
self.moc.endOfSnapshot(self.structure)
end
method collectSnapshotRequests(sr : Sequence) is do
self.moc.collectSnapshotRequests(self.structure, sr)
end
method wrapup() is do
self.moc.wrapup(self.structure)
end
}
// Block inherits ObservableEntity
// AtomicBlock inherits Block
// (in particular, the update operation will be specialized)
// InterfaceBlock inherits Block
aspect abstract class InterfaceBlock {
// most important operations for interface blocks : they are responsible for semantic adaptation
// => will be specialized
operation adaptIn() is abstract
operation adaptOut() is abstract
// operations necessary for hierarchical execution, delegated to the internal model
method prep() is do
self.internal.prep()
end
method setup() is do
self.internal.setup()
end
method collectInitialSnapshotRequests(sr : Sequence) is do
self.internal.collectInitialSnapshotRequests(sr)
// TODO adapt collected requests ?
end
method startOfSnapshot() is do
self.internal.startOfSnapshot()
end
method reset() is do
self.internal.reset()
end
method update() is do
self.adaptIn()
// TODO startOfUpdate ?
self.internal.update() // delegated to the moc (computes the snapshot without validate)
// TODO endOfUpdate ?
self.adaptOut()
end
method validate() : Boolean is do
result := self.internal.validate()
end
method collectSnapshotRequests(sr : Sequence) is do
self.internal.collectSnapshotRequests(sr)
// TODO adapt collected requests ?
end
method endOfSnapshot() is do
self.internal.endOfSnapshot()
end
method wrapup() is do
self.internal.wrapup()
end
}
/*** Model structure ***/
aspect class NamedEntity {
// operations for properties
operation hasProperty(propname : String) : Boolean is abstract
operation addProperty(propname : String, propvalue : Object) is abstract
operation removeProperty(propname : String) is abstract
operation getProperty(propname : String) : Object is abstract
}
aspect class BlockStructure {
// operations necessary for hierarchical execution, delegated to all blocks in the structure
operation prep() is do
self.blocks.each{b| b.prep()}
end
operation setup() is do
self.blocks.each{b| b.setup()}
end
operation collectInitialSnapshotRequests(sr : Sequence) is do
self.blocks.each{b| b.collectInitialSnapshotRequests(sr)}
end
operation startOfSnapshot() is do
self.blocks.each{b| b.startOfSnapshot()}
end
operation reset() is do
self.blocks.each{b| b.reset()}
end
operation validate() : Boolean is do
result := self.blocks.forAll{b| b.validate()}
end
operation endOfSnapshot() is do
self.blocks.each{b| b.endOfSnapshot()}
end
operation collectSnapshotRequests(sr : Sequence) is do
self.blocks.each{b| b.collectSnapshotRequests(sr)}
end
operation wrapup() is do
self.blocks.each{b| b.wrapup()}
end
// to create relations
operation createRelation(sourcePin : Pin, targetPin : Pin) : Relation is abstract
}
aspect class Relation {
operation initialize(sourcePin : Pin, targetPin : Pin) : Relation is abstract
}
PK
{@, , = fr.supelec.modhelx/src/kermeta/core/abstractSemanticsImpl.kmt/*
* $Id:$
* Creation : May 15, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* hardebolle
*/
package modhelx::core;
require kermeta
require "./abstractSemantics.kmt"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using modhelx::core
/*
* This file contains the implementation of basic features of the abstract semantics
* with a logging system
*/
/*** Utilities on all ModHel'X elements ***/
enumeration LogLevel { info ; debug ; }
aspect class NamedEntity {
// For handling logs
attribute logLevel : LogLevel
operation setLogLevel(logLevel : LogLevel) : Void is do
self.logLevel := logLevel
end
operation getLogLevel() : LogLevel is do
result := self.logLevel
end
operation isLogLevelOFF() : Boolean is do
result := (self.logLevel != LogLevel.info) and (self.logLevel != LogLevel.debug)
end
operation isLogLevelINFO() : Boolean is do
result := self.logLevel == LogLevel.info or self.logLevel == LogLevel.debug
end
operation isLogLevelDEBUG() : Boolean is do
result := self.logLevel == LogLevel.debug
end
// For handling properties
operation hasProperty(propname : String) : Boolean is do
result := self.properties.exists{p|p.key == propname}
end
operation addProperty(propname : String, propvalue : Object) is do
var prop : StringToObjectMapEntry init StringToObjectMapEntry.new
prop.key := propname
prop.~value := propvalue
self.properties.add(prop)
end
operation removeProperty(propname : String) is do
var entries : Sequence init self.properties.reject{entry|entry.key == propname}
self.properties.clear()
self.properties.addAll(entries)
end
operation getProperty(propname : String) : Object is do
var entry : StringToObjectMapEntry init self.properties.detect{p|p.key == propname}
var propvalue : Object
propvalue := if entry != void then entry.~value end
result := propvalue
end
operation propertiesToString() : String is do
var s : String init "["
self.properties.each{p|s := s+p.key+"="+p.~value.toString()+", "}
result := s + "]"
end
}
/*** Basic implementation of a MoC ***/
// basic implementation =
// log + delegation to the block structure + snapshot request collection
class ModelOfComputationImpl inherits ModelOfComputation {
// storage of local snapshot requests
reference snapshotRequests : Sequence
// storage of tokens values
reference tokenValues : Hashtable
// replaces constructor
operation initialize() : ModelOfComputationImpl is do
self.tokenValues := Hashtable.new
self.snapshotRequests := Sequence.new
result := self
end
// operations for tokens
method getTokenValue(t : Token) : Object is do
result := self.tokenValues.getValue(t)
end
method setTokenValue(t : Token, val : Object) is do
self.tokenValues.put(t,val)
end
method createToken(val : Object) : Token is do
var tok : Token init Token.new
tok.setOwnerMoC(self)
self.setTokenValue(tok,val)
result := tok
end
// delegation to the block structure
method prep(s : BlockStructure) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": prep") end
s.prep()
end
method setup(s : BlockStructure) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": setup") end
s.setup()
end
method collectInitialSnapshotRequests(s : BlockStructure, sr : Sequence) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": collectInitialSnapshotRequests") end
s.collectInitialSnapshotRequests(self.snapshotRequests) // local collection of snapshot requests
sr.addAll(self.snapshotRequests) // provide requests to hierarchy
end
method startOfSnapshot(s : BlockStructure) is do
if self.isLogLevelINFO() then stdio.writeln("*** " + self.name + ": startOfSnapshot") end
s.startOfSnapshot()
end
method reset(s : BlockStructure) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": reset") end
s.reset()
end
// not delegated : will be specialized for reflecting the semantics of each moc
method schedule(s : BlockStructure) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": schedule") end
end
method update(s : BlockStructure) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": update") end
end
method propagate(s : BlockStructure) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": propagate") end
end
method canGoFurther(s : BlockStructure) : Boolean is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": canGoFurther") end
result := false
end
// delegation to the block structure
method validate(s : BlockStructure) : Boolean is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": validate") end
result := s.validate()
end
method endOfSnapshot(s : BlockStructure) is do
if self.isLogLevelINFO() then stdio.writeln("*** " + self.name + ": endOfSnapshot") end
s.endOfSnapshot()
// clear all constraints from snapshot before collecting new constraints
self.snapshotRequests.clear()
end
method collectSnapshotRequests(s : BlockStructure, sr : Sequence) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": collectSnapshotRequests") end
s.collectSnapshotRequests(self.snapshotRequests)
sr.addAll(self.snapshotRequests)
end
method wrapup(s : BlockStructure) is do
if self.isLogLevelDEBUG() then stdio.writeln("*** " + self.name + ": wrapup") end
s.wrapup()
end
method toString() : String is do
result := "MoC:" + self.name
end
}
/*** Basic implementation of other elements ***/
aspect class Token {
reference ownerMoC : ModelOfComputation
operation setOwnerMoC(moc : ModelOfComputation) is do
self.ownerMoC := moc
end
operation getValue() : Object is do
result := self.ownerMoC.getTokenValue(self)
end
}
aspect class Pin {
reference tokens : seq Token[0..*]
operation addToken(token : Token) is do
self.tokens.add(token)
end
operation getToken(remove : Boolean) : Token is do
var tok : Token init self.tokens.at(0)
result := tok
if(remove) then
self.tokens.remove(tok)
end
end
operation hasToken() : Boolean is do
result := self.tokens.size() > 0
end
operation getTokens() : seq Token [0..*] is do
result := self.tokens
end
operation clearTokens() is do
self.tokens.clear()
end
method toString() : String is do
result := self.name + "(owner=" + self.owner.name + ")"
end
}
aspect abstract class UpdateTrigger {
attribute timeOfUpdate : Integer
reference entityToUpdate : ObservableEntity
operation getEntityToUpdate() : ObservableEntity is do
result := self.entityToUpdate
end
operation setEntityToUpdate(o: ObservableEntity) is do
self.entityToUpdate := o
end
operation getTimeOfUpdate() : Integer is do
result := self.timeOfUpdate
end
operation setTimeOfUpdate(t: Integer) is do
self.timeOfUpdate := t
end
operation trigger() is do
self.entityToUpdate.update()
end
method toString() : String is do
result := "<"+self.entityToUpdate.name.toString() + ","+self.timeOfUpdate.toString()+">"
end
}
aspect class SnapshotRequest {
method prepareToTrigger() is do // here use "method" because redefining operations from the super class
//do nothing
end
}
aspect abstract class ObservableEntity {
operation addPin(name : String) : Pin is do
var pin : Pin init Pin.new
pin.name := name
self.interface.add(pin)
result := pin
end
operation getPin(name : String) : Pin is do
var pin : Pin init self.interface.detect{p|p.name == name}
// if several pins have the same name,
// will return the first pin that has the specified name
if pin==void then
var e : Exception init Exception.new
e.message := "Cannot find pin with name "+name+" in the interface of entity"+self.toString()
raise e
end
result := pin
end
operation interfaceToString() : String is do
var s : String init "["
self.interface.each{p|
s := s + p.name+", "
}
result := s + "]"
end
}
aspect class Model {
operation initialize(name : String) : Model is do
self.name := name
result := self
end
method setLogLevel(logLevel : LogLevel) is do
self.logLevel := logLevel
self.structure.setLogLevel(logLevel)
self.moc.setLogLevel(logLevel)
end
method toString() : String is do
result := "Model:"+self.name + ":\n " + self.moc.toString() + "\n " + self.structure.toString()+"]"
end
}
// log on all block operations
aspect abstract class Block {
method prep() is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> prep") end
end
method setup() is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> setup") end
end
method collectInitialSnapshotRequests(sr : Sequence) is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> collectInitialSnapshotRequests") end
end
method startOfSnapshot() is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> startOfSnapshot") end
end
method reset() is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> reset") end
end
method update() is do
if self.isLogLevelINFO() then stdio.writeln(self.name + " -> update") end
end
method validate() : Boolean is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> validate") end
result := true
end
method endOfSnapshot() is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> endOfSnapshot") end
end
method collectSnapshotRequests(sr : Sequence) is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> collectSnapshotRequests") end
end
method wrapup() is do
if self.isLogLevelDEBUG() then stdio.writeln(self.name + " -> wrapup") end
end
method toString() : String is do
result := "Block:" + self.name + "" + self.interfaceToString() + "" + self.propertiesToString() + ""
end
}
aspect class BlockStructure {
operation createRelation(sourcePin : Pin, targetPin : Pin) : Relation is do
var r : Relation init Relation.new.initialize(sourcePin, targetPin)
self.relations.add(r)
result := r
end
// logs
method setLogLevel(logLevel : LogLevel) is do
self.logLevel := logLevel
self.blocks.each{b| b.setLogLevel(logLevel)}
end
method toString() : String is do
var s : String init "BlockStructure:\n blocks: "
self.blocks.each{b|s := s + b.toString() + ", "}
s := s + "\n rels: "
self.relations.each{r|s := s + r.toString() + ", "}
s := s + ""
result := s
end
}
aspect class Relation {
operation initialize(sourcePin : Pin, targetPin : Pin) : Relation is do
self.source := sourcePin
self.target := targetPin
result := self
end
method toString() : String is do
result := self.source.toString() + "->" + self.target.toString()
end
}
PK
Nv@e e 7 fr.supelec.modhelx/src/kermeta/core/executionEngine.kmt/*
* $Id:$
* Creation : May 15, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* hardebolle
*/
package modhelx::engine;
require kermeta
require "./abstractSemantics.kmt"
require "./abstractSemanticsImpl.kmt"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using kermeta::io
using modhelx::core
class Engine inherits NamedEntity {
reference rootModel : Model
attribute maxNumberOfSnapshots : Integer
operation initialize(model : Model, nbsnap : Integer) : Engine is do
self.rootModel := model
self.maxNumberOfSnapshots := nbsnap
self.setLogLevel(LogLevel.info) // by default, log level is info
result := self
end
method setLogLevel(logLevel : LogLevel) is do
self.logLevel := logLevel
self.rootModel.setLogLevel(logLevel)
end
operation run() is do
if self.isLogLevelDEBUG() then
// print the modhelx model
stdio.writeln(self.rootModel.toString())
end
// preparation of the model
self.rootModel.prep()
// execution setup
self.rootModel.setup()
// collect initial snapshot requests
var isr : Sequence init Sequence.new
self.rootModel.collectInitialSnapshotRequests(isr)
if self.isLogLevelDEBUG() then
stdio.write(" -> (engine) Initial snapshot requests collected: ")
isr.each{s|
stdio.write(s.toString()+", ")
}
stdio.write("\n")
end
var nbsnaps : Integer init 0
// loop of successive snapshots
// snapshots are made if there are snapshot requests, in the limit of maxNumberOfSnapshots
from var snapshotRequested : Boolean init isr.size() > 0 until not snapshotRequested or nbsnaps >= self.maxNumberOfSnapshots
loop
// snapshot !
self.rootModel.startOfSnapshot()
from var snapValidated : Boolean init false until snapValidated
loop
self.rootModel.reset()
self.rootModel.update()
snapValidated := self.rootModel.validate()
end
self.rootModel.endOfSnapshot()
// collect snapshot requests
var sr : Sequence init Sequence.new
self.rootModel.collectSnapshotRequests(sr)
if self.isLogLevelDEBUG() then
stdio.write(" -> (engine) Snapshot requests collected: ")
sr.each{s|
stdio.write(s.toString()+", ")
}
stdio.write("\n")
end
snapshotRequested := sr.size > 0
nbsnaps := nbsnaps + 1
end
// execution wrapup
self.rootModel.wrapup()
end
}
PK
(w@g g - fr.supelec.modhelx/src/kermeta/core/utils.kmt/*
* $Id:$
* Creation : June 3, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* hardebolle
*/
package modhelx::utils;
require kermeta
require "./abstractSemantics.kmt"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using modhelx::core
/*** Utils ***/
class BlockStructureNavigationHelper {
reference blocks : oset Block[0..*]
reference pinSuccessors : Hashtable>
reference pinPredecessors : Hashtable>
reference outgoingRels : Hashtable>
reference incomingRels : Hashtable>
reference blockSuccessors : Hashtable>
reference blockPredecessors : Hashtable>
reference filteredBlockSuccessors : Hashtable>
reference filteredBlockPredecessors : Hashtable>
operation initialize(struct : BlockStructure) : BlockStructureNavigationHelper is do
pinSuccessors := Hashtable>.new
pinPredecessors := Hashtable>.new
outgoingRels := Hashtable>.new
incomingRels := Hashtable>.new
blockSuccessors := Hashtable>.new
blockPredecessors := Hashtable>.new
filteredBlockSuccessors := Hashtable>.new
filteredBlockPredecessors := Hashtable>.new
blocks.addAll(struct.blocks)
var rels : Sequence init struct.relations.reject{r|
(not r.source.owner.isInstanceOf(Block)) or (not r.target.owner.isInstanceOf(Block))
}
/* OR use the following version
var rels : Sequence init struct.relations.reject{r|
r.source.owner.isKindOf(Model) or r.target.owner.isKindOf(Model)
}
*/
rels.each{r|
// stdio.writeln(r.toString())
self.addToList(pinSuccessors, r.source, r.target)
self.addToList(pinPredecessors, r.target, r.source)
self.addToList(outgoingRels, r.source, r)
self.addToList(incomingRels, r.target, r)
self.addToList(blockSuccessors, r.source.owner.asType(Block), r.target.owner.asType(Block))
self.addToList(blockPredecessors, r.target.owner.asType(Block), r.source.owner.asType(Block))
// VOIR comment rendre indep de la propriété ?
if not r.source.hasProperty("NotInstantaneouslyDependent") and not r.target.hasProperty("NotInstantaneouslyDependent") then
self.addToList(filteredBlockSuccessors, r.source.owner.asType(Block), r.target.owner.asType(Block))
self.addToList(filteredBlockPredecessors, r.target.owner.asType(Block), r.source.owner.asType(Block))
end
}
result := self
end
operation addToList(map : Hashtable>, key : T, elem : U) is do
var list : OrderedSet init map.getValue(key)
if list==void then
list := OrderedSet.new
map.put(key,list)
end
list.add(elem)
//stdio.writeln("after addToList map=["+map.keys().each{k|stdio.write("("+k.toString()+":"+map.getValue(k).toString()+")")})
end
operation getPinSuccessors(p : Pin) : OrderedSet is do
var res : OrderedSet init pinSuccessors.getValue(p)
result := if res != void then res else OrderedSet.new end
end
operation getPinPredecessors(p : Pin) : OrderedSet is do
var res : OrderedSet init pinPredecessors.getValue(p)
result := if res != void then res else OrderedSet.new end
end
operation getOutgoingRelations(p : Pin) : OrderedSet is do
var res : OrderedSet init outgoingRels.getValue(p)
result := if res != void then res else OrderedSet.new end
end
operation getIncomingRelations(p : Pin) : OrderedSet is do
var res : OrderedSet init incomingRels.getValue(p)
result := if res != void then res else OrderedSet.new end
end
operation getBlockSuccessors(b : Block) : OrderedSet is do
var res : OrderedSet init blockSuccessors.getValue(b)
result := if res != void then res else OrderedSet.new end
end
operation getBlockPredecessors(b : Block) : OrderedSet is do
var res : OrderedSet init blockPredecessors.getValue(b)
result := if res != void then res else OrderedSet.new end
end
operation getFilteredBlockSuccessors(b : Block) : OrderedSet is do
var res : OrderedSet init filteredBlockSuccessors.getValue(b)
result := if res != void then res else OrderedSet.new end
end
operation getFilteredBlockPredecessors(b : Block) : OrderedSet is do
var res : OrderedSet init filteredBlockPredecessors.getValue(b)
result := if res != void then res else OrderedSet.new end
end
operation isInputPin(p : Pin) : Boolean is do
result := self.getPinPredecessors(p).size()>0 // input if it is the target of at least one relation
end
operation isOutputPin(p : Pin) : Boolean is do
result := self.getPinSuccessors(p).size()>0 // output if it is the source of at least one relation
end
operation topoSort() : OrderedSet is do
var visitedBlocks : Set init Set.new
var orderedBlockList : OrderedSet init OrderedSet.new
var sinkBlocks : Sequence init blocks.select{b| self.getFilteredBlockSuccessors(b).size()==0}
sinkBlocks.each{sinkBlock|
self.visit(sinkBlock, visitedBlocks,orderedBlockList)
}
result := orderedBlockList
end
operation visit(b : Block, visitedBlocks : set Block[0..*], orderedBlocks : oset Block[0..*]) is do
if not visitedBlocks.contains(b) then
visitedBlocks.add(b)
self.getFilteredBlockPredecessors(b).each{pred|
self.visit(pred,visitedBlocks,orderedBlocks)
}
orderedBlocks.add(b)
end
end
}
PK
@bٸ ' fr.supelec.modhelx/src/kermeta/main.kmt/*
* $Id:$
* Creation : May 15, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* hardebolle
*/
@mainClass "modhelx::ModHelX"
@mainOperation "main"
package modhelx;
require kermeta
require "./core/abstractSemantics.kmt"
require "./core/abstractSemanticsImpl.kmt"
require "./core/executionEngine.kmt"
require "./mocs/abstractDEMoC.kmt"
require "./mocs/concurrentDEMoC.kmt"
require "./mocs/sequentialDEMoC.kmt"
require "./mocs/DELib.kmt"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using kermeta::io
using modhelx::core
using modhelx::engine
using modhelx::mocs::de
/*
* This file contains a main for test purpose
* It creates a very simple model and executes it according to ConcurrentDEMoC
* (does not work with SequentialDEMoC)
*/
class ModHelX {
operation main() : Void is do
var model : modhelx::core::Model
// builds the model
model := buildModel()
// executes the model
var nbsnap : Integer init 4 //for tests purpose, replace by stdio.read("Number of snapshots to compute :").toInteger
var eng : Engine init Engine.new.initialize(model, nbsnap)
eng.setLogLevel(LogLevel.info) // possible log levels: debug or info
eng.run()
end
/*
* Builds a DE model for test purpose
* Can be used both with sequential and concurrent DE
*/
operation buildModel() : Model is do
// new test model
var model : Model init Model.new.initialize("myModel")
// DE MoC
// CAUTION this example does not work with SequentialDEMoC, USE ONLY ConcurrentDEMoC
var democ : AbstractDEMoC init ConcurrentDEMoC.new
democ.initialize()
model.moc := democ
// new structure for the model
var struct : BlockStructure init BlockStructure.new
model.structure := struct
/*
// this block emits a constant value with a given period (time step)
var deconst : Block init DEConstant.new.initialize(1,2) // val, timestep
struct.blocks.add(deconst)
*/
// this block is a configurable scenario player
var splay : DEScenarioPlayer init DEScenarioPlayer.new.initialize()
struct.blocks.add(splay)
splay.addPin("addLeftOp")
splay.addPin("addRightOp")
// its scenario is the following:
// at time 0 :
// - emits 2 on pin addLeftOp
// - emits 3 on pin addRightOp
// at time 10 :
// - emits -6 on pin addLeftOp
// - emits 6 on pin addRightOp
splay.addEventToScenario(0,2,"addLeftOp")// time, val, pin
splay.addEventToScenario(0,3,"addRightOp")// time, val, pin
splay.addEventToScenario(10,-6,"addLeftOp")
splay.addEventToScenario(10,6,"addRightOp")
// this block adds the values found on its input pins, therefore:
// -> at time 0 its output will be 5 (2+3)
// -> at time 10 its output will be 0 (-6+6)
var deadd : Block init DEAdder.new.initialize()
struct.blocks.add(deadd)
// this block prints the value found on its input pins on the standard output at the end of the snapshot
var deprint : Block init DEPrinter.new.initialize()
struct.blocks.add(deprint)
// relations to connect the blocks
struct.createRelation(splay.getPin("addLeftOp"), deadd.getPin("in1"))
struct.createRelation(splay.getPin("addRightOp"), deadd.getPin("in2"))
struct.createRelation(deadd.getPin("out"), deprint.getPin("in"))
result := model
end
}
PK
&@T+ + - fr.supelec.modhelx/src/kermeta/mocs/DELib.kmt/*
* $Id:$
* Creation : May 15, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* hardebolle
*/
package modhelx::mocs::de;
require kermeta
require "../core/abstractSemantics.kmt"
require "../core/abstractSemanticsImpl.kmt"
require "abstractDEMoC.kmt"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using modhelx::core
using modhelx::core::utils
/*** DE Atomic Block : Constant Emitter ***/
class DEConstant inherits AtomicBlock {
reference democ : AbstractDEMoC
attribute timeOfNextUpdate : Integer
operation initialize(val : Integer, timeStep : Integer) : DEConstant is do
self.name := "DEConstant"
self.setValue(val)
self.setTimeStep(timeStep)
self.addPin("out")
self.setFirstTimeOfEmit(0)
self.timeOfNextUpdate := 0
result := self
end
//------------------
// Properties of the block
//------------------
operation setValue(val : Integer) is do
self.addProperty("value",val)
end
operation getValue() : Integer is do
result := self.getProperty("value").asType(Integer)
end
operation setFirstTimeOfEmit(val : Integer) is do
self.addProperty("firstTimeOfEmit",val)
end
operation getFirstTimeOfEmit() : Integer is do
result := self.getProperty("firstTimeOfEmit").asType(Integer)
end
operation setTimeStep(val : Integer) is do
self.addProperty("timeStep",val)
end
operation getTimeStep() : Integer is do
result := self.getProperty("timeStep").asType(Integer)
end
//------------------
// Semantics of the block
//------------------
method setup() is do
super()
self.democ := self.structure.model.moc.asType(AbstractDEMoC)
end
method collectInitialSnapshotRequests(sr : Sequence) is do
super(sr)
var myrequest : SnapshotRequest init SnapshotRequest.new
myrequest.setEntityToUpdate(self)
myrequest.setTimeOfUpdate(self.getFirstTimeOfEmit())
sr.add(myrequest)
end
method update() is do
super()
// emit a token on each pin (all are outputs)
// [all produced tokens are always processed at the current time -> no need to put a timestamp, the MoC handles this]
self.interface.each{p|
p.addToken(self.democ.createEvent(self.getValue()))
}
end
method endOfSnapshot() is do
super()
// CAUTION : access to current time of snapshot in the moc... TO KEEP ?
self.timeOfNextUpdate := self.democ.currentTime + self.getTimeStep()
end
method collectSnapshotRequests(sr : Sequence) is do
super(sr)
var myrequest : SnapshotRequest init SnapshotRequest.new
myrequest.setEntityToUpdate(self)
myrequest.setTimeOfUpdate(self.timeOfNextUpdate)
sr.add(myrequest)
end
}
/*** DE Atomic Block : Printer ***/
class DEPrinter inherits AtomicBlock {
reference democ : AbstractDEMoC
reference receivedTokens : seq Token[0..*]
operation initialize() : DEPrinter is do
self.name := "DEPrinter"
self.addPin("in")
result := self
end
method setup() is do
super()
self.democ := self.structure.model.moc.asType(AbstractDEMoC)
end
method reset() is do
super()
// clear the list of received tokens
self.receivedTokens.clear()
end
method update() is do
super()
// get the tokens on each pin (all are inputs), store them, then remove then from the pin
self.interface.each{p|
self.receivedTokens.addAll(p.tokens)
p.tokens.clear()
}
end
method endOfSnapshot() is do
super()
// print the tokens and remove the info on these tokens from the moc tables (the tokens have already been removed from the list of events to process)
self.receivedTokens.each{t|
stdio.writeln("Token received: [val="+self.democ.getEventValue(t).toString()+",timestamp="
+self.democ.getEventTimestamp(t).toString()
//+",dest="
//+self.democ.getEventDestination(t).toString
+"]")
// KEEP THIS ? OR RELY ON RESET OP ?
self.democ.removeEventFromValueDestTimeTables(t)
}
end
}
/*** DE Atomic Block : Adder ***/
class DEAdder inherits AtomicBlock {
reference democ : AbstractDEMoC
reference receivedTokens : seq Token[0..*]
operation initialize() : DEAdder is do
self.name := "DEAdder"
self.addPin("in1")
self.addPin("in2")
self.addPin("out")
result := self
end
method setup() is do
super()
self.democ := self.structure.model.moc.asType(AbstractDEMoC)
end
method reset() is do
super()
// clear the list of received tokens
self.receivedTokens.clear()
end
method update() is do
super()
// result of addition
var sum : Integer init 0
// get the tokens on each input pin, compute the sum, then remove then from the pin
self.interface.select{p| democ.navHelper.isInputPin(p)}.each{p|
stdio.writeln("input pin p:"+p.toString())
p.tokens.each{t|
stdio.writeln("token on p:"+t.toString())
sum := sum + democ.getTokenValue(t).asType(Integer)
self.receivedTokens.add(t)
}
p.tokens.clear()
}
// produce a token on output pins with value sum
self.interface.select{p| democ.navHelper.isOutputPin(p)}.each{p|
p.addToken(self.democ.createEvent(sum))
}
end
method endOfSnapshot() is do
super()
// remove the info on the consummed tokens from the moc tables (the tokens have already been removed from the list of events to process)
self.receivedTokens.each{t|
// KEEP THIS ? OR RELY ON RESET OP ?
self.democ.removeEventFromValueDestTimeTables(t)
}
end
}
/*** DE Atomic Block : ScenarioPlayer ***/
// a scenario is made of several events : at the given time, the value is produced on the specified pin
class DEScenarioEvent inherits Comparable {
reference val : Object
reference pin : Pin
attribute time : Integer
operation initialize(t : Integer, v : Object, p : Pin) : DEScenarioEvent is do
self.val := v
self.time := t
self.pin := p
result := self
end
method compareTo(other : Object) : Integer is do
var o : DEScenarioEvent init other.asType(DEScenarioEvent)
if self.time == o.time then
result := 0
else
if self.time < o.time then
result := -1
else //self.time > o.time
result := 1
end
end
end
method toString() : String is do
result := "DEScenarioEvent{time="+self.time.toString()+",val="+self.val.toString()+",pin="+self.pin.name.toString()+"}"
end
}
// the scenario player produces the planned events at the specified time on the specified pins
class DEScenarioPlayer inherits AtomicBlock {
reference democ : AbstractDEMoC
reference plannedEvents : OrderedSet
reference currentEventsToPlay : OrderedSet
operation initialize() : DEScenarioPlayer is do
self.name := "DEScenarioPlayer"
self.plannedEvents := OrderedSet.new
self.currentEventsToPlay := OrderedSet.new
result := self
end
operation addEventToScenario(time : Integer, val : Object, pinname : String) is do
var event : DEScenarioEvent init DEScenarioEvent.new.initialize(time,val,self.getPin(pinname))
self.plannedEvents.add(event)
end
operation sortEvents() is do
var list : Sequence init Sequence.new
from var scenLength : Integer init self.plannedEvents.size() until scenLength==0
loop
// chercher l'evenement de time min dans le scenario
var minEvent : DEScenarioEvent init self.plannedEvents.first()
from var i : Integer init 1 until i == scenLength
loop
if self.plannedEvents.at(i) < minEvent then
minEvent := self.plannedEvents.at(i)
end
i := i+1
end
// le mettre dans la liste, et le retirer du scenario retirer de l'oset, et inserer en fin de sequence
list.add(minEvent)
self.plannedEvents.remove(minEvent)
scenLength := self.plannedEvents.size()
end
// remettre tous les evenements dans l'ordre dans le scenario
self.plannedEvents.addAll(list)
self.plannedEvents.each{e|stdio.write(e.toString()+",")}
end
method setup() is do
super()
self.democ := self.structure.model.moc.asType(AbstractDEMoC)
// sort scenario events by time
self.sortEvents()
stdio.writeln(self.toString()+"->"+self.scenarioToString())
end
method collectInitialSnapshotRequests(sr : Sequence) is do
super(sr)
// if there are events to play in the scenario
if not self.plannedEvents.empty() then
// get next scenario event to play
var nextevent : DEScenarioEvent init self.plannedEvents.first()
// if there are several events to play at the same time, only the first one is necessary to create the snapshot request
// create a request corresponding to the time of this event
var myrequest : SnapshotRequest init SnapshotRequest.new
myrequest.setEntityToUpdate(self)
myrequest.setTimeOfUpdate(nextevent.time)
sr.add(myrequest)
end
end
method startOfSnapshot() is do
super()
// clear all previously played events
self.currentEventsToPlay.clear()
end
method reset() is do
super()
// clear previous tokens from pins not necessary since they are consummed by the DE moc at propagate (?)
// determine which events are to be played at this time (time is computed at startOfSnapshot in DE)
self.currentEventsToPlay.addAll(self.plannedEvents.select{e| e.time==self.democ.currentTime})
end
method update() is do
super()
// if there are no events to play, then this block should not be updated (problem with time/snapshot requests ?)
if self.currentEventsToPlay.empty() then
var e : Exception init Exception.new
e.message := "Cannot update "+self.name.toString()+" : there are no events in the scenario to play at this time."
raise e
end
// play event(s) (all are played at current time, which should normally be accurate with respect to e.time)
self.currentEventsToPlay.each{e|
e.pin.addToken(self.democ.createEvent(e.val))
}
end
method endOfSnapshot() is do
super()
// remove played events from scenario
self.currentEventsToPlay.each{e|
self.plannedEvents.remove(e)
}
end
method collectSnapshotRequests(sr : Sequence) is do
super(sr)
// if there are events to play in the scenario
if not self.plannedEvents.empty() then
// get next scenario event to play
var nextevent : DEScenarioEvent init self.plannedEvents.first()
// if there are several events to play at the same time, only the first one is necessary to create the snapshot request
// create a request corresponding to the time of this event
var myrequest : SnapshotRequest init SnapshotRequest.new
myrequest.setEntityToUpdate(self)
myrequest.setTimeOfUpdate(nextevent.time)
sr.add(myrequest)
end
end
operation scenarioToString() : String is do
var s : String init "scenario={"
self.plannedEvents.each{e|s := s+e.toString+","}
result := s + "}"
end
}
PK
{@:| 5 fr.supelec.modhelx/src/kermeta/mocs/abstractDEMoC.kmt/*
* $Id:$
* Creation : June 6, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* jacquet_chr
*/
package modhelx::mocs::de;
require kermeta
require "../core/abstractSemantics.kmt"
require "../core/abstractSemanticsImpl.kmt"
require "../core/utils.kmt"
using modhelx::core
using modhelx::utils
using kermeta::standard
using kermeta::utils
/*** DE Triggers ***/
// In DE, a block can be updated either because of a snapshot request, or because of an event
class DEEventToProcess inherits UpdateTrigger {
reference democ : AbstractDEMoC
reference event : Token
operation initialize(democ : AbstractDEMoC, event : Token) : DEEventToProcess is do
self.democ := democ
self.event := event
self.setEntityToUpdate(self.democ.getEventDestination(event).owner)
self.setTimeOfUpdate(self.democ.getEventTimestamp(event))
result := self
end
method prepareToTrigger() is do
self.democ.getEventDestination(self.event).addToken(self.event)
end
method toString() : String is do
var s : String init super()
result := s + "(event="+self.event.toString()+")"
end
}
abstract class AbstractDEMoC inherits ModelOfComputationImpl {
// static set of blocks in topological order
reference blocks : OrderedSet
reference navHelper : BlockStructureNavigationHelper
// state of the model
attribute currentTime : Integer
reference triggers : oset UpdateTrigger[0..*]
// (eventValues already exists as tokenValues)
reference eventTimestamps : Hashtable
reference eventDestinations : Hashtable
//------------------
// Operations for events
//------------------
operation createEvent(val : Object) : Token is do
// create the token and store its value
var e : Token init self.createToken(val)
// no timestamp
// return the token
result := e
end
operation createEventWithTimestamp(val : Object, time : Integer) : Token is do
// create the token and store its value
var e : Token init self.createToken(val)
// then add time
self.eventTimestamps.put(e,time)
// return the token
result := e
end
operation createEventWithTimestampAtCurrentTime(val : Object) : Token is do
result := self.createEventWithTimestamp(val,self.currentTime)
end
operation setEventValue(t : Token, val : Object) : Token is do
self.setTokenValue(t, val)
result := t
end
operation setEventTimestamp(t : Token, time : Integer) : Token is do
self.eventTimestamps.put(t, time)
result := t
end
operation setEventDestination(t : Token, destination : Pin) : Token is do
self.eventDestinations.put(t, destination)
result := t
end
operation getEventValue(t : Token) : Object is do
result := self.getTokenValue(t)
end
operation getEventTimestamp(t : Token) : Integer is do
result := self.eventTimestamps.getValue(t)
end
operation getEventDestination(t : Token) : Pin is do
result := self.eventDestinations.getValue(t)
end
operation removeEventFromValueDestTimeTables(t : Token) is do
self.tokenValues.remove(t)
self.eventDestinations.remove(t)
self.eventTimestamps.remove(t)
end
//------------------
// Special property for loops
//------------------
// the DE MoC manages pins with special properties for dealing with loops : NotInstantaneouslyDependent,true/false
operation setNotInstantaneouslyDependent(p : Pin) is do
p.addProperty("NotInstantaneouslyDependent", true)
end
operation removeNotInstantaneouslyDependent(p : Pin) is do
p.removeProperty("NotInstantaneouslyDependent")
end
operation isNotInstantaneouslyDependent(p : Pin) : Boolean is do
result := p.hasProperty("NotInstantaneouslyDependent")
end
}PK
{@=" " 7 fr.supelec.modhelx/src/kermeta/mocs/concurrentDEMoC.kmt/*
* $Id:$
* Creation : May 15, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* hardebolle
*/
package modhelx::mocs::de;
require kermeta
require "../core/abstractSemantics.kmt"
require "../core/abstractSemanticsImpl.kmt"
require "../core/utils.kmt"
require "DELib.kmt"
require "abstractDEMoC.kmt"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using modhelx::core
using modhelx::utils
/*** DE Model of Computation ***/
class ConcurrentDEMoC inherits AbstractDEMoC {
// state of the MoC for snapshot computation
reference currentBlockToUpdate : Block
reference triggersToProcess : oset UpdateTrigger[0..*]
reference processedTriggers : oset UpdateTrigger[0..*]
method initialize() : ModelOfComputationImpl is do
super()
self.name := "ConcurrentDEMoC"
self.eventTimestamps := Hashtable.new
self.eventDestinations := Hashtable.new
result := self
end
//------------------
// Semantics of DE
//------------------
method prep(s : BlockStructure) is do
super(s)
end
method setup(s : BlockStructure) is do
super(s) // setup the model (hierarchical)
// initialization of time
self.currentTime := 0
// static topological sort
self.navHelper := BlockStructureNavigationHelper.new.initialize(s)
self.blocks := navHelper.topoSort()
end
method collectInitialSnapshotRequests(s : BlockStructure, sr : Sequence) is do
super(s,sr) // hierarchical collect + local storage of requests
end
method startOfSnapshot(s : BlockStructure) is do
super(s)
// add all the snapshot requests to the list of triggers (which may already contain events)
// QUESTION : do this in the collect requests ?
self.snapshotRequests.each{req|
self.triggers.add(req)
}
if self.isLogLevelDEBUG() then
stdio.write("triggers=[")
self.triggers.each{u|stdio.write(u.toString()+", ")}
stdio.writeln("]")
end
// then compute time from the list of triggers
if not self.triggers.empty() then
var minTimestamp : Integer init self.triggers.any().getTimeOfUpdate()
self.triggers.each{t|
if t.getTimeOfUpdate() < minTimestamp then
minTimestamp := t.getTimeOfUpdate()
end
}
self.currentTime := minTimestamp
if self.isLogLevelINFO() or self.isLogLevelDEBUG() then stdio.writeln("[currentTime="+self.currentTime.toString()+"]") end
else
var e : Exception init Exception.new
e.message := "Cannot compute time of snapshot in DE because the list of triggers is empty."
raise e
end
// save the state of the model in case of non validate (TODO)
end
method reset(s : BlockStructure) is do
super(s)
// reset data to its value of the startOfSnashot (TODO)
// build the list of triggers to process at the current time
self.triggersToProcess.clear()
self.triggersToProcess.addAll(self.triggers.select{t|t.getTimeOfUpdate()==self.currentTime})
// clear the list of processed triggers
self.processedTriggers.clear()
end
method schedule(s : BlockStructure) is do
super(s)
// iterate on the blocks in the topological order
var b : Block
var continue : Boolean init true
from var it : Iterator init self.blocks.iterator() until (not it.hasNext()) or (not continue)
loop
b := it.next()
// select all triggers concerning the current block
var tlist : Sequence init self.triggersToProcess.select{t|t.getEntityToUpdate()==b}
// if there are triggers for this block
if not tlist.empty() then
continue := false
// then this block is the current block to update
self.currentBlockToUpdate := b
// make each trigger deliver the necessary info for the block to be updated
tlist.each{u|
u.prepareToTrigger()
// and remove the triggers that have been processed
self.processedTriggers.add(u)
self.triggersToProcess.remove(u)
}
end
end
end
method update(s : BlockStructure) is do
super(s)
// update the block chosen at schedule
self.currentBlockToUpdate.update()
end
method propagate(s : BlockStructure) is do
super(s)
// create triggers from produced events
// select the pins of the updated block which have successor(s)
// (those pins may also have predecessors in the case they are inputs/outputs, but we don't care)
var ouputPinsOfUpdatedBlock : Sequence init self.currentBlockToUpdate.interface.select{p|
self.navHelper.getPinSuccessors(p).size() > 0
}
// for all the produced events, create triggers and put them in the list of triggers to process (since they are produced at the current time !)
ouputPinsOfUpdatedBlock.each{pin|
self.createTriggersFromEvents(pin,self.triggersToProcess)
}
end
operation createTriggersFromEvents(pin : Pin, trigList : Set) is do
pin.getTokens().each{t|
// each token has to be copied for each destination = each target of each a relation leaving the pin
self.navHelper.getPinSuccessors(pin).each{dest|
// make a copy of the value of the token
// [IMPORTANT CSQ => when tokens are put on the inputs of a model / outputs of a block,
// it is necessary to provide their value to the corresponding moc ]
var val : Object init self.getEventValue(t)
// then create a new event with this value at the current time
var copy : Token init self.createEventWithTimestampAtCurrentTime(val)
// set the right destination
self.setEventDestination(copy, dest)
// put each copy in the list of events
trigList.add(DEEventToProcess.new.initialize(self,copy))
}
// forget about the data about the original token, just keep the copies
self.removeEventFromValueDestTimeTables(t)
}
// then remove all tokens from p (or wait for reset ??? in any case, data about these tokens have been removed already...)
pin.clearTokens()
end
method canGoFurther(s : BlockStructure) : Boolean is do
super(s)
if self.isLogLevelDEBUG() then
stdio.write("triggers=[")
self.triggersToProcess.each{u|stdio.write(u.toString()+", ")}
stdio.writeln("]")
end
// can go further if there are still triggers to process at the current time
result := not self.triggersToProcess.empty()
end
method validate(s : BlockStructure) : Boolean is do
var res : Boolean init super(s) // true
result := res
end
method endOfSnapshot(s : BlockStructure) is do
super(s)
/* // put produced events on the outputs of the model ????
// CAUTION : in practice, this never happens ! it must be handled in the endOfUpdate operation...
*/
// update the state of the model (TODO)
// remove all the triggers that have been processed from the global trigger list
var newTriggerList : Sequence init self.triggers.reject{u| self.processedTriggers.contains(u)}
// also remove all triggers that are Snapshot requests (since there will be a new collect of snapshot requests)
newTriggerList := newTriggerList.reject{u| u.isKindOf(SnapshotRequest)}
self.triggers.clear()
self.triggers.addAll(newTriggerList)
end
method collectSnapshotRequests(s : BlockStructure, sr : Sequence) is do
super(s,sr) // hierarchical collect + local storage of requests
// check that there are no more triggers at current time (should not happen)
if not self.triggers.select{t|t.getTimeOfUpdate()==self.currentTime}.empty() then
var e : Exception init Exception.new
e.message := "In the end of snapshot, all triggers at current time should have been processed."
raise e
end
// in case there are events remaining in the list of triggers, they have a date in the future
// -> post a snapshot request on the min date
// (this part should not be necessary because all events produced by blocks are at the current time so there should not be events with
// date in the future in the list...)
if not self.triggers.empty() then
var minTrigger : UpdateTrigger init self.triggers.any()
self.triggers.each{t|
if t.getTimeOfUpdate() < minTrigger.getTimeOfUpdate() then
minTrigger := t
end
}
var request : SnapshotRequest init SnapshotRequest.new
request.setEntityToUpdate(minTrigger.getEntityToUpdate())
request.setTimeOfUpdate(minTrigger.getTimeOfUpdate())
sr.add(request)
end
end
method wrapup(s : BlockStructure) is do
super(s)
end
}
PK
{@ik) ) 7 fr.supelec.modhelx/src/kermeta/mocs/sequentialDEMoC.kmt/*
* $Id:$
* Creation : June 6, 2012
* Licence : EPL
* Copyright (c) 2012 Supelec.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors :
* Computer Science Department, Supelec
* Contacts :
* Cecile.Hardebolle@supelec.fr
* Christophe.Jacquet@supelec.fr
* Frederic.Boulanger@supelec.fr
* Authors :
* jacquet_chr
*/
package modhelx::mocs::de;
require kermeta
require "../core/abstractSemantics.kmt"
require "../core/abstractSemanticsImpl.kmt"
require "../core/utils.kmt"
require "abstractDEMoC.kmt"
using kermeta::standard
using kermeta::persistence
using kermeta::exceptions
using kermeta::utils
using modhelx::core
using modhelx::utils
using modhelx::mocs::de
/*** Sequential-DE Model of Computation ***/
class SequentialDEMoC inherits AbstractDEMoC {
// state of the MoC for snapshot computation
reference activeBlock : ObservableEntity
attribute executionComplete : Boolean
reference triggersToProcess : oset UpdateTrigger[0..*]
reference processedTriggers : oset UpdateTrigger[0..*]
method initialize() : ModelOfComputationImpl is do
super()
self.name := "SequentialDEMoC"
self.eventTimestamps := Hashtable.new
self.eventDestinations := Hashtable.new
result := self
end
//------------------
// Semantics of Sequential-DE
//------------------
method prep(s : BlockStructure) is do
super(s)
end
method setup(s : BlockStructure) is do
super(s) // setup the model (hierarchical)
// initialization of time
self.currentTime := 0
// static topological sort
self.navHelper := BlockStructureNavigationHelper.new.initialize(s)
self.blocks := navHelper.topoSort()
end
method collectInitialSnapshotRequests(s : BlockStructure, sr : Sequence) is do
super(s,sr) // hierarchical collect + local storage of requests
end
method startOfSnapshot(s : BlockStructure) is do
super(s)
// add all the snapshot requests to the list of triggers (which may already contain events)
// QUESTION : do this in the collect requests ?
self.snapshotRequests.each{req|
self.triggers.add(req)
}
if self.isLogLevelDEBUG() then
stdio.write("triggers=[")
self.triggers.each{u|stdio.write(u.toString()+", ")}
stdio.writeln("]")
end
// determine the new active block
// is the latest active block still active?
var activeTrigger : UpdateTrigger init self.triggers.detect{t|t.getEntityToUpdate() == self.activeBlock}
if activeTrigger != void then
// yes -> just set the new time
self.currentTime := activeTrigger.getTimeOfUpdate()
else
// else compute the minimum time from the list of triggers
if not self.triggers.empty() then
var minTimestamp : Integer init void
self.triggers.each{t|
var timeOfUpdate : Integer init t.getTimeOfUpdate()
if timeOfUpdate != void and (minTimestamp == void or timeOfUpdate < minTimestamp) then
minTimestamp := timeOfUpdate
self.activeBlock := t.getEntityToUpdate()
end
}
self.currentTime := minTimestamp
else
var e : Exception init Exception.new
e.message := "Cannot compute time of snapshot in DE because the list of triggers is empty."
raise e
end
end
if self.isLogLevelINFO() then stdio.writeln("[currentTime="+self.currentTime.toString()+"]") end
// save the state of the model in case of non validate (TODO)
end
method reset(s : BlockStructure) is do
super(s)
// reset data to its value of the startOfSnashot (TODO)
// build the list of triggers to process at the current time
self.triggersToProcess.clear()
self.triggersToProcess.addAll(self.triggers.select{t|t.getTimeOfUpdate()==void or t.getTimeOfUpdate()==self.currentTime})
// clear the list of processed triggers
self.processedTriggers.clear()
// get ready to execute a new activity
self.executionComplete := true
end
method schedule(s : BlockStructure) is do
super(s)
if activeBlock == void then
activeBlock := self.triggersToProcess.detect{t|t.getTimeOfUpdate() == void}.getEntityToUpdate()
if isLogLevelDEBUG() then
stdio.writeln("Last active block finished. Scheduling new active block " + activeBlock.toString())
end
end
// select all triggers concerning the current block
var tlist : Sequence init self.triggersToProcess.select{t|t.getEntityToUpdate()==activeBlock}
// if there are triggers for this block
// make each trigger deliver the necessary info for the block to be updated
tlist.each{u|
u.prepareToTrigger()
// and remove the triggers that have been processed
self.processedTriggers.add(u)
self.triggersToProcess.remove(u)
}
end
method update(s : BlockStructure) is do
super(s)
// update the block chosen at schedule
self.activeBlock.update()
// did the execution complete? it is so iff the block has produced tokens in output
var outputPinsOfUpdatedBlock : Sequence init self.activeBlock.interface.select{p|
self.navHelper.getPinSuccessors(p).size() > 0
}
self.executionComplete := outputPinsOfUpdatedBlock.forAll{p|p.hasToken()}
if isLogLevelDEBUG() then
stdio.writeln("Execution of block " + self.activeBlock.name + " complete? " + self.executionComplete.toString())
end
end
method propagate(s : BlockStructure) is do
super(s)
// create triggers from produced events
// select the pins of the updated block which have successor(s)
// (those pins may also have predecessors in the case they are inputs/outputs, but we don't care)
var outputPinsOfUpdatedBlock : Sequence init self.activeBlock.interface.select{p|
self.navHelper.getPinSuccessors(p).size() > 0
}
// for all the produced events, create triggers and put them in the list of triggers to process (since they are produced at the current time !)
outputPinsOfUpdatedBlock.each{pin|
self.createTriggersFromEvents(pin,self.triggersToProcess)
}
if self.executionComplete then
// the active block will change in the next schedule
activeBlock := void
end
end
operation createTriggersFromEvents(pin : Pin, trigList : Set) is do
pin.getTokens().each{t|
// each token has to be copied for each destination = each target of each a relation leaving the pin
self.navHelper.getPinSuccessors(pin).each{dest|
// make a copy of the value of the token
// [IMPORTANT CSQ => when tokens are put on the inputs of a model / outputs of a block,
// then create a new event with this value at the current time
var copy : Token init self.createEventWithTimestamp(void, void)
// set the right destination
self.setEventDestination(copy, dest)
// put each copy in the list of events
trigList.add(DEEventToProcess.new.initialize(self,copy))
}
// forget about the data about the original token, just keep the copies
self.removeEventFromValueDestTimeTables(t)
}
// then remove all tokens from p (or wait for reset ??? in any case, data about these tokens have been removed already...)
pin.clearTokens()
end
method canGoFurther(s : BlockStructure) : Boolean is do
super(s)
if self.isLogLevelDEBUG() then
stdio.write("triggersToProcess=[")
self.triggersToProcess.each{u|stdio.write(u.toString()+", ")}
stdio.writeln("]")
end
// can go further if there are still triggers to process at the current time
// AND there is no active block (the latest execution is complete)
result := (not self.triggersToProcess.empty()) and self.executionComplete
if self.isLogLevelDEBUG() then
stdio.writeln("Can go further? " + result.toString())
end
end
method validate(s : BlockStructure) : Boolean is do
var res : Boolean init super(s) // true
result := res
end
method endOfSnapshot(s : BlockStructure) is do
super(s)
/* // put produced events on the outputs of the model ????
// CAUTION : in practice, this never happens ! it must be handled in the endOfUpdate operation...
*/
// update the state of the model (TODO)
// in the sequential MoC there may be some "triggersToProcess" that
// may not be processed at the current snapshot. So we need to add
// the triggers from "triggersToProcess" to the main trigger list
self.triggers.addAll(self.triggersToProcess)
// remove all the triggers that have been processed from the global trigger list
var newTriggerList : Sequence init self.triggers.reject{u| self.processedTriggers.contains(u)}
// also remove all triggers that are Snapshot requests (since there will be a new collect of snapshot requests)
newTriggerList := newTriggerList.reject{u| u.isKindOf(SnapshotRequest)}
self.triggers.clear()
self.triggers.addAll(newTriggerList)
if isLogLevelDEBUG() then
stdio.write("triggers for next snapshot = [")
self.triggers.each{u|stdio.write(u.toString()+", ")}
stdio.writeln("]")
end
end
method collectSnapshotRequests(s : BlockStructure, sr : Sequence) is do
super(s,sr) // hierarchical collect + local storage of requests
// check that there are no more triggers at current time (should not happen)
if not self.triggers.select{t|t.getTimeOfUpdate()==self.currentTime}.empty() then
var e : Exception init Exception.new
e.message := "In the end of snapshot, all triggers at current time should have been processed."
raise e
end
// in case there are events remaining in the list of triggers, they have a date in the future
// -> post a snapshot request on the min date
// (this part should not be necessary because all events produced by blocks are at the current time so there should not be events with
// date in the future in the list...)
if not self.triggers.empty() then
// in the sequential MoC, some triggers may have no time
var minTrigger : UpdateTrigger init void
self.triggers.each{t|
if t.getTimeOfUpdate() != void then
if minTrigger == void then
minTrigger := t
else
if t.getTimeOfUpdate() < minTrigger.getTimeOfUpdate() then
minTrigger := t
end
end
end
}
if minTrigger != void then
var request : SnapshotRequest init SnapshotRequest.new
request.setEntityToUpdate(minTrigger.getEntityToUpdate())
request.setTimeOfUpdate(minTrigger.getTimeOfUpdate())
sr.add(request)
end
end
end
method wrapup(s : BlockStructure) is do
super(s)
end
}
PK
u@ڭ, fr.supelec.modhelx/.projectPK
u@wJ J = fr.supelec.modhelx/.settings/org.eclipse.core.resources.prefsPK
(w@H * g fr.supelec.modhelx/metamodel/modhelx.ecorePK
u@qST . fr.supelec.modhelx/metamodel/modhelx.ecorediagPK C@ fr.supelec.modhelx/model/PK
&@a! ! 9 fr.supelec.modhelx/src/kermeta/core/abstractSemantics.kmtPK
{@, , = N fr.supelec.modhelx/src/kermeta/core/abstractSemanticsImpl.kmtPK
Nv@e e 7 B fr.supelec.modhelx/src/kermeta/core/executionEngine.kmtPK
(w@g g - fr.supelec.modhelx/src/kermeta/core/utils.kmtPK
@bٸ ' 5 fr.supelec.modhelx/src/kermeta/main.kmtPK
&@T+ + - D fr.supelec.modhelx/src/kermeta/mocs/DELib.kmtPK
{@:| 5 p fr.supelec.modhelx/src/kermeta/mocs/abstractDEMoC.kmtPK
{@=" " 7 fr.supelec.modhelx/src/kermeta/mocs/concurrentDEMoC.kmtPK
{@ik) ) 7 ۣ fr.supelec.modhelx/src/kermeta/mocs/sequentialDEMoC.kmtPK