Package org.pshdl.interpreter

Source Code of org.pshdl.interpreter.HDLFrameInterpreter$HDLFrameInterpreterFactory

/*******************************************************************************
* PSHDL is a library and (trans-)compiler for PSHDL input. It generates
*     output suitable for implementation or simulation of it.
*
*     Copyright (C) 2013 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.interpreter;

import java.math.BigInteger;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.pshdl.interpreter.access.BigAccesses;
import org.pshdl.interpreter.access.EncapsulatedAccess;
import org.pshdl.interpreter.access.EncapsulatedAccess.RegUpdater;
import org.pshdl.interpreter.access.LongAccesses;
import org.pshdl.interpreter.frames.BigIntegerFrame;
import org.pshdl.interpreter.frames.ExecutableFrame;
import org.pshdl.interpreter.frames.IDebugListener;
import org.pshdl.interpreter.frames.LongFrame;

public final class HDLFrameInterpreter implements IHDLBigInterpreter {
  public static class HDLFrameInterpreterFactory implements IHDLInterpreterFactory<HDLFrameInterpreter> {

    private final ExecutableModel model;
    private final IDebugListener listener;

    public HDLFrameInterpreterFactory(ExecutableModel model, IDebugListener listener) {
      super();
      this.model = model;
      this.listener = listener;
    }

    @Override
    public HDLFrameInterpreter newInstance() {
      return new HDLFrameInterpreter(model, listener);
    }

  }

  /**
   * Marker that an accessIndex is of kind BigInteger. The accessIndex is
   * binary ored with this
   */
  private static final int BIG_MARKER = 0x80000000;
  /**
   * A mask to convert to get the real accessIndex if it is ored with
   * BIG_MARKER
   */
  private static final int BIG_MASK = BIG_MARKER - 1;

  /**
   * The model to execute
   */
  public final ExecutableModel model;

  /**
   * The storage for internals that have a width <= 64
   */
  public final long storage[], storage_prev[];
  /**
   * The storage for internals that have a width >=64;
   */
  public final BigInteger big_storage[], big_storage_prev[];

  /**
   * The {@link EncapsulatedAccess} for each accessIndex
   */
  public final EncapsulatedAccess[] internals, internals_prev;

  /**
   * An {@link EncapsulatedAccess} for the full variable width of a variable
   */
  public final EncapsulatedAccess[] full;

  /**
   * A mapping from baseName of internal to the accessIndex (for accessing
   * {@link #internals} or {@link #internals_prev})
   */
  private final Map<String, Integer> accessIdxMap = new TreeMap<>();

  /**
   * A mapping from baseName to the index in {@link #full}
   */
  private final Map<String, Integer> varIdxMap = new TreeMap<>();

  /**
   * The current simulation deltaCycle. That is, how often the run method was
   * called
   */
  private int deltaCycle = 0;

  /**
   * An index when a certain internal was last updated
   */
  public final long[] deltaUpdates;

  /**
   * The frames that get executed
   */
  private final ExecutableFrame frames[];
  private final IDebugListener listener;

  public HDLFrameInterpreter(ExecutableModel model, IDebugListener listener) {
    this.model = model;
    this.internals = new EncapsulatedAccess[model.internals.length];
    this.internals_prev = new EncapsulatedAccess[model.internals.length];
    this.full = new EncapsulatedAccess[model.variables.length];
    this.listener = listener;
    final int storageSize = createVarIndex(model);
    createInternals(model);
    this.storage = new long[storageSize];
    this.storage_prev = new long[storageSize];
    this.big_storage = new BigInteger[storageSize];
    this.big_storage_prev = new BigInteger[storageSize];
    for (int i = 0; i < big_storage.length; i++) {
      big_storage[i] = BigInteger.ZERO;
      big_storage_prev[i] = BigInteger.ZERO;
    }
    deltaUpdates = new long[storageSize];
    final Frame[] frames = model.frames;
    this.frames = new ExecutableFrame[frames.length];
    for (int i = 0; i < frames.length; i++) {
      if (frames[i].maxDataWidth > 64) {
        this.frames[i] = new BigIntegerFrame(listener, this, frames[i], internals, internals_prev);
      } else {
        this.frames[i] = new LongFrame(listener, this, frames[i], internals, internals_prev);
      }
    }
  }

  private int createVarIndex(ExecutableModel model) {
    int currentIdx = 0;
    for (int i = 0; i < model.variables.length; i++) {
      final VariableInformation vi = model.variables[i];
      varIdxMap.put(vi.name, i);
      int accessIndex = currentIdx;
      int size = 1;
      for (final int d : vi.dimensions) {
        size *= d;
      }
      currentIdx += size;
      final InternalInformation ii = new InternalInformation(vi.name, vi);
      if (vi.width > 64) {
        accessIdxMap.put(vi.name, accessIndex | BIG_MARKER);
        full[i] = BigAccesses.getInternal(ii, accessIndex & BIG_MASK, false, this);
      } else {
        accessIdxMap.put(vi.name, accessIndex);
        full[i] = LongAccesses.getInternal(ii, accessIndex, false, this);
      }
      if (vi.isRegister) {
        accessIndex = currentIdx;
        if (vi.width > 64) {
          accessIdxMap.put(vi.name + InternalInformation.REG_POSTFIX, accessIndex | BIG_MARKER);
        } else {
          accessIdxMap.put(vi.name + InternalInformation.REG_POSTFIX, accessIndex);
        }
        currentIdx += size;
      }
    }
    return currentIdx;
  }

  private void createInternals(ExecutableModel model) {
    for (int i = 0; i < model.internals.length; i++) {
      final InternalInformation ii = model.internals[i];
      final String baseName = ii.baseName(false, true);
      final Integer accessIndex = accessIdxMap.get(baseName);
      if (accessIndex == null)
        throw new IllegalArgumentException("No accessIndex for:" + baseName);
      if (((accessIndex & BIG_MARKER) == BIG_MARKER)) {
        internals[i] = BigAccesses.getInternal(ii, accessIndex & BIG_MASK, false, this);
        internals_prev[i] = BigAccesses.getInternal(ii, accessIndex & BIG_MASK, true, this);
      } else {
        internals[i] = LongAccesses.getInternal(ii, accessIndex, false, this);
        internals_prev[i] = LongAccesses.getInternal(ii, accessIndex, true, this);
      }
    }
    for (final EncapsulatedAccess ea : internals) {
      if (ea.ii.isShadowReg) {
        final String baseName = ea.ii.baseName(false, false);
        final Integer idx = accessIdxMap.get(baseName);
        if (idx != null) {
          ea.targetAccessIndex = idx;
        } else {
          ea.targetAccessIndex = ea.getAccessIndex();
        }
      }
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#setInput(java.lang.String,
   * java.math.BigInteger, int)
   */
  @Override
  public void setInput(String name, BigInteger value, int... arrayIdx) {
    setInput(getIndex(name), value, arrayIdx);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#setInput(int,
   * java.math.BigInteger, int)
   */
  @Override
  public void setInput(int idx, BigInteger value, int... arrayIdx) {
    final EncapsulatedAccess acc = full[idx];
    if (arrayIdx != null) {
      acc.setOffset(arrayIdx);
    }
    acc.setDataBig(value, deltaCycle, 0);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#setInput(java.lang.String,
   * long, int)
   */
  @Override
  public void setInput(String name, long value, int... arrayIdx) {
    setInput(getIndex(name), value, arrayIdx);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#setInput(int, long, int)
   */
  @Override
  public void setInput(int idx, long value, int... arrayIdx) {
    final EncapsulatedAccess acc = full[idx];
    if (arrayIdx != null) {
      acc.setOffset(arrayIdx);
    }
    acc.setDataLong(value, deltaCycle, 0);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#getIndex(java.lang.String)
   */
  @Override
  public int getIndex(String name) {
    final Integer integer = varIdxMap.get(name);
    if (integer == null)
      throw new IllegalArgumentException("Could not find a variable named:" + name + " valid names are:" + accessIdxMap.keySet());
    return integer;
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org.pshdl.interpreter.IHDLInterpreter#getOutputLong(java.lang.String,
   * int)
   */
  @Override
  public long getOutputLong(String name, int... arrayIdx) {
    return getOutputLong(getIndex(name), arrayIdx);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#getOutputLong(int, int)
   */
  @Override
  public long getOutputLong(int idx, int... arrayIdx) {
    final EncapsulatedAccess acc = full[idx];
    if (arrayIdx != null) {
      acc.setOffset(arrayIdx);
    }
    return acc.getDataLong();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#getOutputBig(java.lang.String,
   * int)
   */
  @Override
  public BigInteger getOutputBig(String name, int... arrayIdx) {
    return getOutputBig(getIndex(name), arrayIdx);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#getOutputBig(int, int)
   */
  @Override
  public BigInteger getOutputBig(int idx, int... arrayIdx) {
    final EncapsulatedAccess acc = full[idx];
    if (arrayIdx != null) {
      acc.setOffset(arrayIdx);
    }
    return acc.getDataBig();
  }

  /*
   * SignedCastTest.main() cast (int<8>) -2 to (uint<16>) : FFFE
   * SignedCastTest.main() cast (int<8>) -2 to (int<16>) : FFFE
   * SignedCastTest.main() cast (int<16>) -255 to (int<8>) : 01
   * SignedCastTest.main() cast (int<16>) -255 to (int<32>) : FFFFFF01
   * SignedCastTest.main() cast (uint<16>) 65535 to (int<32>) : 0000FFFF
   */
  final private Set<RegUpdater> updatedRegs = new LinkedHashSet<>();

  /*
   * (non-Javadoc)
   *
   * @see org.pshdl.interpreter.IHDLInterpreter#run()
   */
  @Override
  public void run() {
    deltaCycle++;
    int epsCycle = 0;
    do {
      updatedRegs.clear();
      epsCycle++;
      if (listener != null) {
        listener.startCycle(deltaCycle, epsCycle, this);
      }
      for (final ExecutableFrame ef : frames) {
        ef.execute(deltaCycle, epsCycle);
      }
      if (!updatedRegs.isEmpty()) {
        if (listener != null) {
          listener.copyingRegisterValues(this);
        }
        for (final RegUpdater ea : updatedRegs) {
          if (ea.isBig) {
            big_storage[ea.accessIdx & BIG_MASK] = big_storage[ea.shadowAccessIdx & BIG_MASK];
          } else {
            storage[ea.accessIdx] = storage[ea.shadowAccessIdx];
          }
        }
      }
    } while (!updatedRegs.isEmpty());
    if (listener != null) {
      listener.doneCycle(deltaCycle, this);
    }
    System.arraycopy(storage, 0, storage_prev, 0, storage.length);
    System.arraycopy(big_storage, 0, big_storage_prev, 0, big_storage.length);
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder();
    sb.append("Current Cycle:" + deltaCycle + "\n");
    for (final Entry<String, Integer> e : accessIdxMap.entrySet()) {
      sb.append('\t').append(e.getKey()).append("=").append(storage[e.getValue() & BIG_MASK]).append('\n');
    }
    return sb.toString();
  }

  @Override
  public String getName(int idx) {
    for (final Entry<String, Integer> e : varIdxMap.entrySet()) {
      if (e.getValue() == idx)
        return e.getKey();
    }
    throw new IllegalArgumentException("No such index:" + idx);
  }

  @Override
  public long getDeltaCycle() {
    return deltaCycle;
  }

  public void addRegUpdate(RegUpdater regUpdater) {
    updatedRegs.add(regUpdater);
  }

  @Override
  public void initConstants() {
    // TODO Auto-generated method stub

  }

  @Override
  public void close() throws Exception {
  }

  @Override
  public void setFeature(Feature feature, Object value) {
    switch (feature) {
    case disableEdges:
    case disableOutputRegs:
      if ((boolean) value)
        throw new IllegalArgumentException("Feature not supported");
    }
  }
}
TOP

Related Classes of org.pshdl.interpreter.HDLFrameInterpreter$HDLFrameInterpreterFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.