diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java index c571236..feb0ab5 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java @@ -13,25 +13,73 @@ public class ChannelState { private DataTransferChannel channel; private Map> childrenMap; - private Map, Map> referenceStructure; + private ReferenceStructure referenceStructure; public ChannelState(DataTransferChannel channel) { this.channel = channel; } - public Map getDependentParams(Map channelParameters) { - Map dependentParams = new HashMap<>(); - if (referenceStructure != null) { - List channelParams = new ArrayList<>(); - for (Selector sel: channel.getAllSelectors()) { - channelParams.add(channelParameters.get(sel)); - } - for (Map.Entry paramEnt: referenceStructure.get(channelParams).entrySet()) { - dependentParams.put(paramEnt.getKey(), paramEnt.getValue()); - } + public DataTransferChannel getChannel() { + return channel; + } + + public Map getDependentParams(Map channelParameters) { + if (referenceStructure == null) { + return null; } - return dependentParams; + return referenceStructure.getDependentParams(channelParameters); } + public void addDependantParam(Map channelParameters, Expression variable, Expression value) { + referenceStructure.addDependantParam(channelParameters, variable, value); + } + private static class ReferenceStructure { + private Map dependentParams = null; + private Map referenceStructure; + + public Map getDependentParams() { + return dependentParams; + } + + public Map getDependentParams(Map channelParameters) { + ReferenceStructure subStructure = this; + for (Selector sel: channelParameters.keySet()) { + if (subStructure.getDependentParams() == null) { + subStructure = subStructure.getReferenceStructure(channelParameters.get(sel)); + } else { + return null; + } + } + return subStructure.getDependentParams(); + } + + public void addDependantParam(Expression variable, Expression value) { + if (dependentParams == null) { + dependentParams = new HashMap<>(); + } + dependentParams.put(variable, value); + } + + public void addDependantParam(Map channelParameters, Expression variable, Expression value) { + ReferenceStructure subStructure = this; + for (Selector sel: channelParameters.keySet()) { + Constant chParam = channelParameters.get(sel); + if (subStructure.referenceStructure == null) { + subStructure.referenceStructure = new HashMap<>(); + } + ReferenceStructure nextStructure = subStructure.referenceStructure.get(chParam); + if (nextStructure == null) { + nextStructure = new ReferenceStructure(); + subStructure.referenceStructure.put(chParam, nextStructure); + } + subStructure = nextStructure; + } + subStructure.addDependantParam(variable, value); + } + + public ReferenceStructure getReferenceStructure(Constant channelParam) { + return referenceStructure.get(channelParam); + } + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java index abfcf67..26d1495 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -14,25 +14,28 @@ import models.dataFlowModel.DataTransferChannel; public class Event { - private DataTransferChannel channel; + private ChannelState channelState; private Expression message; private boolean isInput = false; + private ResourcePath inputResourcePath = null; private Map channelParameters = new HashMap<>(); - private Set inputResources; - private Set outputResources; + private Map dependentParameters = new HashMap<>(); + private Set inputResources = new HashSet<>(); + private Set outputResources = new HashSet<>(); private Set succEvents = new HashSet<>(); private Map> channelSelectorToInputResourcePathParam = new HashMap<>(); private Map> channelSelectorToOutputResourcePathParam = new HashMap<>(); - public Event(DataTransferChannel channel, ChannelState channelState, Expression message, Resource outputResource) { - this.channel = channel; + public Event(ChannelState channelState, Expression message, Resource outputResource) { + this.channelState = channelState; this.message = message; this.isInput = true; this.outputResources.add(outputResource); connectChannelSelectorAndPathParameters(); // Extract channel parameters from the output resource. + DataTransferChannel channel = channelState.getChannel(); List channelSelectors = channel.getAllSelectors(); Set outputResPathSet = null; for (Selector sel: channelSelectors) { @@ -60,13 +63,15 @@ } } - public Event(DataTransferChannel channel, ChannelState channelState, ResourcePath inputResPath, Resource inputResource) { - this.channel = channel; + public Event(ChannelState channelState, ResourcePath inputResPath, Resource inputResource) { + this.channelState = channelState; this.isInput = false; + this.inputResourcePath = inputResPath; this.inputResources.add(inputResource); connectChannelSelectorAndPathParameters(); // Extract channel parameters from the input resource. + DataTransferChannel channel = channelState.getChannel(); List channelSelectors = channel.getAllSelectors(); for (Selector sel: channelSelectors) { if (inputResPath != null) { @@ -83,10 +88,11 @@ channelParameters.put(sel, ancestor.getParameter()); } } - channelParameters.putAll(channelState.getDependentParams(channelParameters)); + updateAllDependentParameters(channelState); } private void connectChannelSelectorAndPathParameters() { + DataTransferChannel channel = channelState.getChannel(); List channelSelectors = channel.getAllSelectors(); for (Selector sel: channelSelectors) { for (ResourcePath resPath: channel.getInputResources()) { @@ -113,9 +119,13 @@ } } } - + public DataTransferChannel getChannel() { - return channel; + return channelState.getChannel(); + } + + public ChannelState getChannelState() { + return channelState; } public Expression getMessage() { @@ -130,6 +140,22 @@ return isInput; } + public Map getChannelParameters() { + return channelParameters; + } + + public void updateDependentParameter(Expression variable, Expression value) { + dependentParameters.put(variable, value); + } + + public void updateAllDependentParameters(ChannelState channelState) { + dependentParameters.putAll(channelState.getDependentParams(channelParameters)); + } + + public ResourcePath getInputResourcePath() { + return inputResourcePath; + } + public Set getInputResources() { return inputResources; } @@ -152,6 +178,12 @@ int paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); resId.setPathParam(paramIdx, channelParameters.get(sel)); } + for (Expression var: dependentParameters.keySet()) { + int paramIdx = resId.getPathParams().indexOf(var); + if (paramIdx >= 0) { + resId.setPathParam(paramIdx, (Constant) dependentParameters.get(var)); + } + } return resId; } @@ -161,6 +193,12 @@ int paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath); resId.setPathParam(paramIdx, channelParameters.get(sel)); } + for (Expression var: dependentParameters.keySet()) { + int paramIdx = resId.getPathParams().indexOf(var); + if (paramIdx >= 0) { + resId.setPathParam(paramIdx, (Constant) dependentParameters.get(var)); + } + } return resId; } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 934f527..7d175d8 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -15,6 +15,7 @@ import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; import models.dataFlowModel.DataTransferChannel; @@ -77,15 +78,49 @@ } }; - for (ChannelMember out: event.getChannel().getOutputChannelMembers()) { - Expression nextResState = event.getChannel().deriveUpdateExpressionOf(out, resouceStateAccessor).getKey(); - ResourceIdentifier outResId = event.getOutputResourceIdentifier(out.getResource()); - if (nextResState instanceof Term) { - nextResState = ((Term) nextResState).reduce(); + DataTransferChannel channel = event.getChannel(); + if (channel.getOutputResources().size() > 0) { + if (!event.isInput()) { + // Update the channel state and resource identifiers by the update of the input resource. + Map>> dependency = channel.fillOutsideResourcePaths(channel.getOutputChannelMembers().iterator().next(), resouceStateAccessor); + for (ChannelMember dependingMem: dependency.keySet()) { + for (ChannelMember dependedMem: dependency.get(dependingMem).getValue()) { + if (event.getInputResourcePath() == dependedMem.getResource()) { + // If a (depending) resource is to be updated by the update of the input resource. + ResourcePath filledResPath = dependency.get(dependingMem).getKey(); + ResourcePath unfilledResPath = dependingMem.getResource(); + ChannelState nextChState = nextSystemState.getChannelState(channel); + for (int i = 0; i < unfilledResPath.getPathParams().size(); i++) { + Expression var = unfilledResPath.getPathParams().get(i); + Expression val = filledResPath.getPathParams().get(i); + boolean isSelector = false; + for (Selector sel: channel.getAllSelectors()) { + if (sel.getExpression().equals(var)) { + isSelector = true; + break; + } + } + if (!isSelector) { + nextChState.addDependantParam(event.getChannelParameters(), var, val); + } + } + nextSystemState.updateChannelState(channel, nextChState); + event.updateAllDependentParameters(nextChState); + } + } + } } - nextSystemState.setResourceState(outResId, nextResState); - for (Event nextEvent: getNextEvents(outResId, nextSystemState)) { - fireEvent(nextEvent, curSystemState, nextSystemState); + // For each output resource, calculate the next state. + for (ChannelMember out: channel.getOutputChannelMembers()) { + Expression nextResState = channel.deriveUpdateExpressionOf(out, resouceStateAccessor).getKey(); + ResourceIdentifier outResId = event.getOutputResourceIdentifier(out.getResource()); + if (nextResState instanceof Term) { + nextResState = ((Term) nextResState).reduce(); + } + nextSystemState.updateResourceState(outResId, nextResState); + for (Event nextEvent: getNextEvents(outResId, nextSystemState)) { + fireEvent(nextEvent, curSystemState, nextSystemState); + } } } } @@ -97,7 +132,7 @@ for (ResourcePath inResPath: channel.getInputResources()) { if (inResId.isInstanceOf(inResPath)) { ChannelState channelState = chEntry.getValue(); - Event nextEvent = new Event(channel, channelState, inResPath, nextSystemState.getResource(inResId)); + Event nextEvent = new Event(channelState, inResPath, nextSystemState.getResource(inResId)); nextEvents.add(nextEvent); } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index 38068f3..18d9a97 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -42,7 +42,7 @@ return null; } - public void setResourceState(ResourceIdentifier resourceIdentifier, Expression resState) { + public void updateResourceState(ResourceIdentifier resourceIdentifier, Expression resState) { Resource res = getResource(resourceIdentifier); if (res !=null) { ResourceState state = res.getState(); @@ -57,6 +57,14 @@ public Map getChannelStates() { return channelStates; } + + public ChannelState getChannelState(DataTransferChannel channel) { + return channelStates.get(channel); + } + + public void updateChannelState(DataTransferChannel channel, ChannelState channelState) { + channelStates.put(channel, channelState); + } public List getEvents() { return events;