/** * PSHDL is a library and (trans-)compiler for PSHDL input. It generates * output suitable for implementation or simulation of it. * * Copyright (C) 2014 Karsten Becker (feedback (at) pshdl (dot) org) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * This License does not grant permission to use the trade names, trademarks, * service marks, or product names of the Licensor, except as required for * reasonable and customary use in describing the origin of the Work. * * Contributors: * Karsten Becker - initial API and implementation */ package org.pshdl.model.utils; import com.google.common.base.Optional; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.xtend2.lib.StringConcatenation; import org.eclipse.xtext.xbase.lib.IterableExtensions; import org.eclipse.xtext.xbase.lib.MapExtensions; import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; import org.eclipse.xtext.xbase.lib.Procedures.Procedure2; import org.pshdl.model.HDLAssignment; import org.pshdl.model.HDLBlock; import org.pshdl.model.HDLDeclaration; import org.pshdl.model.HDLForLoop; import org.pshdl.model.HDLFunctionCall; import org.pshdl.model.HDLIfStatement; import org.pshdl.model.HDLInstantiation; import org.pshdl.model.HDLReference; import org.pshdl.model.HDLRegisterConfig; import org.pshdl.model.HDLResolvedRef; import org.pshdl.model.HDLStatement; import org.pshdl.model.HDLSwitchCaseStatement; import org.pshdl.model.HDLSwitchStatement; import org.pshdl.model.HDLUnit; import org.pshdl.model.HDLUnresolvedFragment; import org.pshdl.model.HDLVariable; import org.pshdl.model.extensions.StringWriteExtension; import org.pshdl.model.utils.HDLQuery; import org.pshdl.model.utils.SyntaxHighlighter; @SuppressWarnings("all") public class ProcessModel { private static AtomicInteger ai = new AtomicInteger(); public Multimap<Integer, HDLStatement> unclockedStatements = LinkedListMultimap.<Integer, HDLStatement>create(); public Multimap<HDLRegisterConfig, HDLStatement> clockedStatements = LinkedListMultimap.<HDLRegisterConfig, HDLStatement>create(); public final static int DEF_PROCESS = (-1); public static ProcessModel toProcessModel(final HDLUnit stmnt) { final ProcessModel pm = new ProcessModel(); ArrayList<HDLStatement> _inits = stmnt.getInits(); final Procedure1<HDLStatement> _function = new Procedure1<HDLStatement>() { public void apply(final HDLStatement s) { ProcessModel _processModel = ProcessModel.toProcessModel(s, ProcessModel.DEF_PROCESS); pm.merge(_processModel); } }; IterableExtensions.<HDLStatement>forEach(_inits, _function); ArrayList<HDLStatement> _statements = stmnt.getStatements(); final Procedure1<HDLStatement> _function_1 = new Procedure1<HDLStatement>() { public void apply(final HDLStatement s) { ProcessModel _processModel = ProcessModel.toProcessModel(s, ProcessModel.DEF_PROCESS); pm.merge(_processModel); } }; IterableExtensions.<HDLStatement>forEach(_statements, _function_1); return pm; } protected static ProcessModel _toProcessModel(final HDLFunctionCall stmnt, final int pid) { ProcessModel _processModel = new ProcessModel(); return _processModel.addUnclocked(pid, stmnt); } protected static ProcessModel _toProcessModel(final HDLInstantiation stmnt, final int pid) { return null; } protected static ProcessModel _toProcessModel(final HDLDeclaration stmnt, final int pid) { return null; } protected static ProcessModel _toProcessModel(final HDLStatement stmnt, final int pid) { throw new RuntimeException(("Not implemented for statement:" + stmnt)); } protected static ProcessModel _toProcessModel(final HDLBlock stmnt, final int pid) { int _xifexpression = (int) 0; Boolean _process = stmnt.getProcess(); if ((_process).booleanValue()) { _xifexpression = ProcessModel.ai.getAndIncrement(); } else { _xifexpression = pid; } final int newPid = _xifexpression; return ProcessModel.<HDLBlock, HDLStatement, ArrayList<HDLStatement>>toProcessModel(stmnt, HDLBlock.fStatements, newPid); } protected static ProcessModel _toProcessModel(final HDLForLoop stmnt, final int pid) { return ProcessModel.<HDLForLoop, HDLStatement, ArrayList<HDLStatement>>toProcessModel(stmnt, HDLForLoop.fDos, pid); } protected static ProcessModel _toProcessModel(final HDLSwitchCaseStatement stmnt, final int pid) { return ProcessModel.<HDLSwitchCaseStatement, HDLStatement, ArrayList<HDLStatement>>toProcessModel(stmnt, HDLSwitchCaseStatement.fDos, pid); } private static <T extends HDLStatement, V extends HDLStatement, C extends Collection<V>> ProcessModel toProcessModel(final T obj, final HDLQuery.HDLFieldAccess<T, C> field, final int pid) { final ProcessModel pm = new ProcessModel(); C _value = field.getValue(obj); for (final V subStmnt : _value) { ProcessModel _processModel = ProcessModel.toProcessModel(subStmnt, pid); pm.merge(_processModel); } final ProcessModel res = new ProcessModel(); Map<Integer, Collection<HDLStatement>> _asMap = pm.unclockedStatements.asMap(); final Procedure2<Integer, Collection<HDLStatement>> _function = new Procedure2<Integer, Collection<HDLStatement>>() { public void apply(final Integer subPid, final Collection<HDLStatement> stmnts) { ArrayList<HDLStatement> _arrayList = new ArrayList<HDLStatement>(stmnts); T _setValue = field.setValue(obj, ((C) _arrayList)); res.unclockedStatements.put(subPid, _setValue); } }; MapExtensions.<Integer, Collection<HDLStatement>>forEach(_asMap, _function); Map<HDLRegisterConfig, Collection<HDLStatement>> _asMap_1 = pm.clockedStatements.asMap(); final Procedure2<HDLRegisterConfig, Collection<HDLStatement>> _function_1 = new Procedure2<HDLRegisterConfig, Collection<HDLStatement>>() { public void apply(final HDLRegisterConfig reg, final Collection<HDLStatement> stmnts) { ArrayList<HDLStatement> _arrayList = new ArrayList<HDLStatement>(stmnts); T _setValue = field.setValue(obj, ((C) _arrayList)); res.clockedStatements.put(reg, _setValue); } }; MapExtensions.<HDLRegisterConfig, Collection<HDLStatement>>forEach(_asMap_1, _function_1); return res; } protected static ProcessModel _toProcessModel(final HDLIfStatement stmnt, final int pid) { final ProcessModel thenPM = new ProcessModel(); ArrayList<HDLStatement> _thenDo = stmnt.getThenDo(); final Procedure1<HDLStatement> _function = new Procedure1<HDLStatement>() { public void apply(final HDLStatement s) { ProcessModel _processModel = ProcessModel.toProcessModel(s, pid); thenPM.merge(_processModel); } }; IterableExtensions.<HDLStatement>forEach(_thenDo, _function); final ProcessModel elsePM = new ProcessModel(); ArrayList<HDLStatement> _elseDo = stmnt.getElseDo(); final Procedure1<HDLStatement> _function_1 = new Procedure1<HDLStatement>() { public void apply(final HDLStatement s) { ProcessModel _processModel = ProcessModel.toProcessModel(s, pid); elsePM.merge(_processModel); } }; IterableExtensions.<HDLStatement>forEach(_elseDo, _function_1); final LinkedHashSet<HDLRegisterConfig> clocks = new LinkedHashSet<HDLRegisterConfig>(); Set<HDLRegisterConfig> _keySet = thenPM.clockedStatements.keySet(); clocks.addAll(_keySet); Set<HDLRegisterConfig> _keySet_1 = elsePM.clockedStatements.keySet(); clocks.addAll(_keySet_1); final ProcessModel res = new ProcessModel(); boolean _or = false; boolean _isEmpty = thenPM.unclockedStatements.isEmpty(); boolean _not = (!_isEmpty); if (_not) { _or = true; } else { boolean _isEmpty_1 = elsePM.unclockedStatements.isEmpty(); boolean _not_1 = (!_isEmpty_1); _or = _not_1; } if (_or) { Collection<HDLStatement> _unclocked = thenPM.getUnclocked(pid); HDLIfStatement _setThenDo = stmnt.setThenDo(_unclocked); Collection<HDLStatement> _unclocked_1 = elsePM.getUnclocked(pid); HDLIfStatement _setElseDo = _setThenDo.setElseDo(_unclocked_1); res.addUnclocked(pid, _setElseDo); } for (final HDLRegisterConfig reg : clocks) { Collection<HDLStatement> _clocked = thenPM.getClocked(reg); HDLIfStatement _setThenDo_1 = stmnt.setThenDo(_clocked); Collection<HDLStatement> _clocked_1 = elsePM.getClocked(reg); HDLIfStatement _setElseDo_1 = _setThenDo_1.setElseDo(_clocked_1); res.addClocked(reg, _setElseDo_1); } return res; } protected static ProcessModel _toProcessModel(final HDLSwitchStatement stmnt, final int pid) { final Map<HDLSwitchCaseStatement, ProcessModel> pms = Maps.<HDLSwitchCaseStatement, ProcessModel>newLinkedHashMap(); final LinkedHashSet<HDLRegisterConfig> clocks = new LinkedHashSet<HDLRegisterConfig>(); boolean hasUnclocked = false; ArrayList<HDLSwitchCaseStatement> _cases = stmnt.getCases(); for (final HDLSwitchCaseStatement caze : _cases) { { final ProcessModel casePM = ProcessModel.toProcessModel(caze, pid); boolean _isEmpty = casePM.unclockedStatements.isEmpty(); boolean _not = (!_isEmpty); if (_not) { hasUnclocked = true; } Set<HDLRegisterConfig> _keySet = casePM.clockedStatements.keySet(); clocks.addAll(_keySet); pms.put(caze, casePM); } } final ProcessModel res = new ProcessModel(); if (hasUnclocked) { final List<HDLSwitchCaseStatement> newCases = Lists.<HDLSwitchCaseStatement>newLinkedList(); final Procedure2<HDLSwitchCaseStatement, ProcessModel> _function = new Procedure2<HDLSwitchCaseStatement, ProcessModel>() { public void apply(final HDLSwitchCaseStatement caze, final ProcessModel caseStatements) { Collection<HDLStatement> _get = caseStatements.unclockedStatements.get(Integer.valueOf(pid)); HDLSwitchCaseStatement _setDos = caze.setDos(_get); newCases.add(_setDos); } }; MapExtensions.<HDLSwitchCaseStatement, ProcessModel>forEach(pms, _function); HDLSwitchStatement _setCases = stmnt.setCases(newCases); res.addUnclocked(pid, _setCases); } for (final HDLRegisterConfig reg : clocks) { { final List<HDLSwitchCaseStatement> newCases_1 = Lists.<HDLSwitchCaseStatement>newLinkedList(); final Procedure2<HDLSwitchCaseStatement, ProcessModel> _function_1 = new Procedure2<HDLSwitchCaseStatement, ProcessModel>() { public void apply(final HDLSwitchCaseStatement caze, final ProcessModel caseStatements) { Collection<HDLStatement> _get = caseStatements.clockedStatements.get(reg); HDLSwitchCaseStatement _setDos = caze.setDos(_get); newCases_1.add(_setDos); } }; MapExtensions.<HDLSwitchCaseStatement, ProcessModel>forEach(pms, _function_1); HDLSwitchStatement _setCases_1 = stmnt.setCases(newCases_1); res.addClocked(reg, _setCases_1); } } return res; } protected static ProcessModel _toProcessModel(final HDLAssignment stmnt, final int pid) { final HDLReference ref = stmnt.getLeft(); if ((ref instanceof HDLUnresolvedFragment)) { throw new RuntimeException(("Not implemented for HDLUnresolvedFragment:" + stmnt)); } final HDLResolvedRef rRef = ((HDLResolvedRef) ref); Optional<HDLVariable> _resolveVar = rRef.resolveVar(); final HDLVariable hVar = _resolveVar.get(); final HDLRegisterConfig regConfig = hVar.getRegisterConfig(); HDLRegisterConfig _registerConfig = hVar.getRegisterConfig(); boolean _tripleNotEquals = (_registerConfig != null); if (_tripleNotEquals) { ProcessModel _processModel = new ProcessModel(); return _processModel.addClocked(regConfig, stmnt); } ProcessModel _processModel_1 = new ProcessModel(); return _processModel_1.addUnclocked(pid, stmnt); } public ProcessModel merge(final ProcessModel model) { boolean _tripleNotEquals = (model != null); if (_tripleNotEquals) { this.unclockedStatements.putAll(model.unclockedStatements); this.clockedStatements.putAll(model.clockedStatements); } return this; } public Collection<HDLStatement> getClocked(final HDLRegisterConfig reg) { return this.clockedStatements.get(reg); } public Collection<HDLStatement> getUnclocked(final int pid) { return this.unclockedStatements.get(Integer.valueOf(pid)); } public ProcessModel addUnclocked(final int pid, final HDLStatement stmnt) { this.unclockedStatements.put(Integer.valueOf(pid), stmnt); return this; } public ProcessModel addClocked(final HDLRegisterConfig config, final HDLStatement stmnt) { this.clockedStatements.put(config, stmnt); return this; } public String toString() { StringConcatenation _builder = new StringConcatenation(); _builder.append("<------------------>"); _builder.newLine(); _builder.append("Unclocked Statements:"); _builder.newLine(); { Map<Integer, Collection<HDLStatement>> _asMap = this.unclockedStatements.asMap(); Set<Map.Entry<Integer, Collection<HDLStatement>>> _entrySet = _asMap.entrySet(); for(final Map.Entry<Integer, Collection<HDLStatement>> e : _entrySet) { _builder.append("Process:"); Integer _key = e.getKey(); _builder.append(_key, ""); _builder.newLineIfNotEmpty(); { Collection<HDLStatement> _value = e.getValue(); for(final HDLStatement s : _value) { SyntaxHighlighter _none = SyntaxHighlighter.none(); String _asString = StringWriteExtension.asString(s, _none); _builder.append(_asString, ""); _builder.newLineIfNotEmpty(); } } } } _builder.newLine(); _builder.append("<------------------>"); _builder.newLine(); _builder.append("Clocked Statements:"); _builder.newLine(); { Map<HDLRegisterConfig, Collection<HDLStatement>> _asMap_1 = this.clockedStatements.asMap(); Set<Map.Entry<HDLRegisterConfig, Collection<HDLStatement>>> _entrySet_1 = _asMap_1.entrySet(); for(final Map.Entry<HDLRegisterConfig, Collection<HDLStatement>> e_1 : _entrySet_1) { _builder.append("Process:"); HDLRegisterConfig _key_1 = e_1.getKey(); _builder.append(_key_1, ""); _builder.newLineIfNotEmpty(); { Collection<HDLStatement> _value_1 = e_1.getValue(); for(final HDLStatement s_1 : _value_1) { SyntaxHighlighter _none_1 = SyntaxHighlighter.none(); String _asString_1 = StringWriteExtension.asString(s_1, _none_1); _builder.append(_asString_1, ""); _builder.newLineIfNotEmpty(); } } } } return _builder.toString(); } public static ProcessModel toProcessModel(final HDLStatement stmnt, final int pid) { if (stmnt instanceof HDLBlock) { return _toProcessModel((HDLBlock)stmnt, pid); } else if (stmnt instanceof HDLForLoop) { return _toProcessModel((HDLForLoop)stmnt, pid); } else if (stmnt instanceof HDLIfStatement) { return _toProcessModel((HDLIfStatement)stmnt, pid); } else if (stmnt instanceof HDLSwitchCaseStatement) { return _toProcessModel((HDLSwitchCaseStatement)stmnt, pid); } else if (stmnt instanceof HDLSwitchStatement) { return _toProcessModel((HDLSwitchStatement)stmnt, pid); } else if (stmnt instanceof HDLAssignment) { return _toProcessModel((HDLAssignment)stmnt, pid); } else if (stmnt instanceof HDLDeclaration) { return _toProcessModel((HDLDeclaration)stmnt, pid); } else if (stmnt instanceof HDLFunctionCall) { return _toProcessModel((HDLFunctionCall)stmnt, pid); } else if (stmnt instanceof HDLInstantiation) { return _toProcessModel((HDLInstantiation)stmnt, pid); } else if (stmnt != null) { return _toProcessModel(stmnt, pid); } else { throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object>asList(stmnt, pid).toString()); } } }