package ua.ansymo.hintco import org.eclipse.emf.common.util.BasicEList type Int wraps int abstract class IDed { String identifier } class HintConfiguration { contains RootCandidateScenario[] candidates contains CosimUnitDeclaration[] csuDeclarations refers VariantDiagram root contains VariantDiagram[] nodes } class VariantDiagram extends IDed { refers VariantDiagram[] children refers Alternative alternative derived String name get { val prefix = identifier+"_" if (alternative !== null){ if (alternative instanceof RootCandidateScenario){ prefix + "sce " + (alternative as RootCandidateScenario).name } else if (alternative instanceof XorPortAdaptation) { prefix + "xor " + (alternative as XorPortAdaptation).name } else if (alternative instanceof XorUnitAdaptation) { prefix + "xor " + (alternative as XorUnitAdaptation).name } else if (alternative instanceof ExtrapolationAdaptation) { prefix + "extra " + (alternative as ExtrapolationAdaptation).name } else if (alternative instanceof InterpolationAdaptation) { prefix + "intra " + (alternative as InterpolationAdaptation).name } else { prefix + "implement" } } else { prefix + "root" } } } abstract class PrecedenceNode { refers PrecedenceNode[] precedes opposite succeeds refers PrecedenceNode[] succeeds opposite precedes refers PrecedenceNode before opposite after refers PrecedenceNode after opposite before } class RootCandidateScenario extends IDed, Alternative, Scenario { derived String name get { identifier + "(w=" + weight + ")" } double stopTime double stepSize double outputStepSize int maxInitIterations = "10" } abstract class Scenario extends IDed { contains UnitInstance[] cosimunits opposite scenario } class HierarchicalCosimUnit extends Scenario,UnitInstance { op boolean valid() { ports.forall[p | p instanceof HierarchicalUnitPort] } } class CosimUnitDeclaration extends IDed { String path String guid } abstract class UnitInstance extends IDed,PrecedenceNode{ refers Scenario scenario opposite cosimunits contains UnitAdaptation adaptation opposite unit contains PortInstance[] ports opposite unit op UnitAdaptation[] selectedAdaptations() { if (adaptation === null){ return new BasicEList(#[]) } if (adaptation.selected){ if (adaptation instanceof DecompositionUnitAdaptation){ return (adaptation as DecompositionUnitAdaptation).selectedAdaptations() } return new BasicEList(#[adaptation]) } return new BasicEList(#[]) } op OutputPortInstance[] getOutputPorts(){ ports.filter(OutputPortInstance).filter[!it.isInput].toEList } op InputPortInstance[] getInputPorts(){ ports.filter(InputPortInstance).filter[it.isInput].toEList } op String toString(){ identifier } } class CosimUnitInstance extends UnitInstance { refers CosimUnitDeclaration[1] declaration } abstract class PortInstance extends PrecedenceNode,IDed { refers UnitInstance unit opposite ports contains PortAdaptation adaptation opposite port op PortAdaptation[] selectedAdaptations() { if (adaptation === null){ return new BasicEList(#[]) } if (adaptation.selected){ if (adaptation instanceof DecompositionPortAdaptation){ return (adaptation as DecompositionPortAdaptation).selectedAdaptations() } return new BasicEList(#[adaptation]) } return new BasicEList(#[]) } op boolean isInput() { false } op boolean getsValueFrom(PortInstance p){ return false } op String toString(){ unit.toString()+"."+identifier } } class HierarchicalUnitPort extends InputPortInstance,OutputPortInstance{ op boolean isInput() { // A port is an input if it gets its value from an external port. val auxIsInput = ! unit.eAllContents.filter(OutputPortInstance).exists[p | p == valueFrom] val auxAltIsInput = altIsInput() if ((auxIsInput && !auxAltIsInput) || (!auxIsInput && auxAltIsInput)){ throw new RuntimeException("Something wrong with the implementation of isInput") } auxIsInput } op boolean altIsInput() { // A port is an input if it is connected to internal input ports or internal unit ports that are inputs themselves. if (valueTo.empty){ false // A port connected to nothing must be an output } else { valueTo.forall[trgP | if (trgP.unit === unit){ false // We don't tolerate feedtrough connections on hierarchical units. } else { val internal = unit.eAllContents.filter(InputPortInstance).exists[ip | ip===trgP] if (! internal ){ false } else if (trgP instanceof HierarchicalUnitPort){ trgP.altIsInput } else { true } } ] } } } class InputPortInstance extends PortInstance { float extrapolationCost = "1.0" refers OutputPortInstance[] internalValueTo opposite internalValueFrom refers OutputPortInstance valueFrom opposite valueTo // Recursively ignore HierarchicalUnitPort and get the OutputPortInstance that generates this value op OutputPortInstance getRealValueFrom() { if (valueFrom instanceof HierarchicalUnitPort){ (valueFrom as HierarchicalUnitPort).realValueFrom } else { valueFrom } } op boolean getsValueFrom(PortInstance p){ if (valueFrom === p){ return true } else if (valueFrom instanceof InputPortInstance){ return (valueFrom as InputPortInstance).getsValueFrom(p) } else { return false } } op boolean isInput() { true } } class OutputPortInstance extends PortInstance { refers InputPortInstance[] valueTo opposite valueFrom refers InputPortInstance[] internalValueFrom opposite internalValueTo op boolean isInput() { false } } abstract class Alternative { int weight boolean selected refers Alternative[] implies } abstract class Adaptation extends Alternative { } abstract class PortAdaptation extends Adaptation { refers PortInstance port opposite adaptation refers DecompositionPortAdaptation parent opposite children op PortInstance adapted() { if (port !== null){ return port } if (parent === null){ return null } return parent.adapted() } } abstract class DecompositionPortAdaptation extends PortAdaptation { contains PortAdaptation[] children opposite parent derived String name get { "(w=" + weight + ")" } op PortAdaptation[] selectedAdaptations() { val res = new BasicEList(children.size) for (c : children.filter[a | a.selected]){ if (c instanceof DecompositionPortAdaptation){ res.addAll(c.selectedAdaptations()) } else { res.add(c) } } return res } } abstract class UnitAdaptation extends Adaptation { refers UnitInstance unit opposite adaptation refers DecompositionUnitAdaptation parent opposite children op UnitInstance adapted() { if (unit !== null){ return unit } if (parent === null){ return null } return parent.adapted() } } abstract class DecompositionUnitAdaptation extends UnitAdaptation { contains UnitAdaptation[] children opposite parent derived String name get { "(w=" + weight + ")" } op UnitAdaptation[] selectedAdaptations() { val res = new BasicEList(children.size) for (c : children.filter[a | a.selected]){ if (c instanceof DecompositionUnitAdaptation){ res.addAll(c.selectedAdaptations()) } else { res.add(c) } } return res } } class XorUnitAdaptation extends DecompositionUnitAdaptation { } class XorPortAdaptation extends DecompositionPortAdaptation { } abstract class ApproximationAdaptation extends PortAdaptation { int order } class MultiRateAdaptation extends UnitAdaptation { int rate derived String name get { rate + "(w=" + weight + ")" } } class PowerBondAdaptation extends UnitAdaptation { refers PortInstance effort refers PortInstance flow refers OutputPortInstance pOut refers InputPortInstance pIn op PowerBondAdaptation getDual() { var PowerBondAdaptation res = null if (effort instanceof InputPortInstance && flow instanceof OutputPortInstance){ res = unit.scenario.cosimunits .flatMap[u | u.eAllContents.filter(PowerBondAdaptation).toIterable] .filter[a | a.effort instanceof OutputPortInstance && a.flow instanceof InputPortInstance] .findFirst[a | (a.effort as OutputPortInstance).valueTo.contains(effort) && (a.flow as InputPortInstance).valueFrom === flow] } else if (effort instanceof OutputPortInstance && flow instanceof InputPortInstance) { res = unit.scenario.cosimunits .flatMap[u | u.eAllContents.filter(PowerBondAdaptation).toIterable] .filter[a | a.effort instanceof InputPortInstance && a.flow instanceof OutputPortInstance] .findFirst[a | (a.effort as InputPortInstance).valueFrom === effort && (a.flow as OutputPortInstance).valueTo.contains(flow)] } else { throw new RuntimeException("Invalid effort and flow in power bond adaptation") } if (res===null){ throw new RuntimeException("Power bond adaptation has no dual") } res } derived String name get { if (effort!==null && flow !== null){ "PBond_" + effort.identifier + "_" + flow.identifier + "(w=" + weight + ")" } else { "PBond(w=" + weight + ")" } } } class ExtrapolationAdaptation extends ApproximationAdaptation { derived String name get { order + "(w=" + weight + ")" } } class RollbackInterpolationAdaptation extends ExtrapolationAdaptation { } class InterpolationAdaptation extends ApproximationAdaptation { derived String name get { order + "(w=" + weight + ")" } }