Package org.pshdl.interpreter.frames

Source Code of org.pshdl.interpreter.frames.BigIntegerFrame

/*******************************************************************************
* 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.frames;

import static java.math.BigInteger.ONE;
import static java.math.BigInteger.ZERO;

import java.math.BigInteger;

import org.pshdl.interpreter.Frame;
import org.pshdl.interpreter.Frame.FastInstruction;
import org.pshdl.interpreter.HDLFrameInterpreter;
import org.pshdl.interpreter.access.EncapsulatedAccess;

public final class BigIntegerFrame extends ExecutableFrame {
  private final BigInteger stack[];
  private final BigInteger constants[];
  private final IDebugListener listener;

  public BigIntegerFrame(IDebugListener listener, HDLFrameInterpreter fir, Frame f, EncapsulatedAccess internals[], EncapsulatedAccess internals_prev[]) {
    super(fir, f, internals, internals_prev);
    this.stack = new BigInteger[f.maxStackDepth];
    this.constants = f.constants;
    this.listener = listener;
  }

  @Override
  public void execute(int deltaCycle, int epsCycle) {
    int stackPos = -1;
    currentPos = 0;
    int arrayPos = -1;
    BigInteger b = BigInteger.ZERO, a = BigInteger.ZERO;
    if (listener != null) {
      listener.startFrame(uniqueID, deltaCycle, epsCycle, this);
    }
    for (final FastInstruction f : instructions) {
      if (f.popA) {
        a = stack[stackPos--];
      }
      if (f.popB) {
        b = stack[stackPos--];
      }
      switch (f.inst) {
      case noop:
        break;
      case and: {
        stack[++stackPos] = b.and(a);
        break;
      }
      case arith_neg: {
        stack[++stackPos] = a.negate();
        break;
      }
      case bit_neg: {
        stack[++stackPos] = a.not();
        break;
      }
      case bitAccessSingle: {
        final int bit = f.arg1;
        stack[++stackPos] = a.shiftRight(bit).and(BigInteger.ONE);
        break;
      }
      case bitAccessSingleRange: {
        final int highBit = f.arg1;
        final int lowBit = f.arg2;
        final BigInteger mask = BigInteger.ONE.shiftLeft((highBit - lowBit) + 1).subtract(BigInteger.ONE);
        final BigInteger current = a.shiftRight(lowBit).and(mask);
        stack[++stackPos] = current;
        break;
      }
      case cast_int: {
        final int targetWidth = f.arg1;
        final int currWidth = f.arg2;
        if (targetWidth >= currWidth) {
          // Do nothing
        } else {
          final BigInteger mask = BigInteger.ONE.shiftLeft(targetWidth).subtract(BigInteger.ONE);
          System.out.println("BigIntegerFrame.execute() cast int<" + currWidth + "> to int<" + targetWidth + "> masking with:" + mask.toString(16));
          BigInteger t = a;
          t = t.and(mask);
          if (t.testBit(targetWidth - 1)) { // MSB is set
            if (t.signum() > 0) {
              t = t.negate();
            }
          } else {
            if (t.signum() < 0) {
              t = t.negate();
            }
          }
          stack[++stackPos] = t;
        }
        break;
      }
      case cast_uint: {
        final BigInteger mask = BigInteger.ONE.shiftLeft(f.arg1).subtract(BigInteger.ONE);
        stack[++stackPos] = a.and(mask);
        break;
      }
      case concat: {
        stack[++stackPos] = b.shiftLeft(f.arg2).or(a);
        break;
      }
      case const0:
        stack[++stackPos] = ZERO;
        break;
      case const1:
        stack[++stackPos] = ONE;
        break;
      case const2:
        stack[++stackPos] = BigInteger.valueOf(2);
        break;
      case constAll1:
        stack[++stackPos] = BigInteger.ONE.shiftLeft(f.arg1).subtract(BigInteger.ONE);
        break;
      case div: {
        stack[++stackPos] = b.divide(a);
        break;
      }
      case eq: {
        stack[++stackPos] = b.equals(a) ? ONE : ZERO;
        break;
      }
      case greater: {
        stack[++stackPos] = b.compareTo(a) > 0 ? ONE : ZERO;
        break;
      }
      case greater_eq: {
        stack[++stackPos] = b.compareTo(a) >= 0 ? ONE : ZERO;
        break;
      }
      case less: {
        stack[++stackPos] = b.compareTo(a) < 0 ? ONE : ZERO;
        break;
      }
      case less_eq: {
        stack[++stackPos] = b.compareTo(a) <= 0 ? ONE : ZERO;
        break;
      }
      case loadConstant:
        stack[++stackPos] = constants[f.arg1];
        break;
      case loadInternal:
        stack[++stackPos] = getInternal(f.arg1, arrayPos).getDataBig();
        arrayPos = -1;
        break;
      case logiAnd: {
        stack[++stackPos] = ((!ZERO.equals(b)) && (!ZERO.equals(a))) ? ONE : ZERO;
        break;
      }
      case logiOr: {
        stack[++stackPos] = (!ZERO.equals(b) || !ZERO.equals(a)) ? ONE : ZERO;
        break;
      }
      case logiNeg: {
        if (ZERO.equals(a)) {
          stack[++stackPos] = ONE;
        } else {
          stack[++stackPos] = ZERO;
        }
        break;
      }
      case minus: {
        stack[++stackPos] = b.subtract(a);
        break;
      }
      case mul: {
        stack[++stackPos] = b.multiply(a);
        break;
      }
      case mod:
        stack[++stackPos] = b.mod(a);
        break;
      case pow:
        stack[++stackPos] = b.pow(a.intValue());
        break;
      case not_eq: {
        stack[++stackPos] = !b.equals(a) ? ONE : ZERO;
        break;
      }
      case or: {
        stack[++stackPos] = b.or(a);
        break;
      }
      case plus: {
        stack[++stackPos] = b.add(a);
        break;
      }
      case sll: {
        stack[++stackPos] = b.shiftLeft(a.intValue());
        break;
      }
      case sra: {
        stack[++stackPos] = b.shiftRight(a.intValue());
        break;
      }
      case srl: {
        stack[++stackPos] = srl(b, f.arg1, a.intValue());
        break;
      }
      case xor: {
        stack[++stackPos] = b.xor(a);
        break;
      }
      case isFallingEdge: {
        final int off = f.arg1;
        final EncapsulatedAccess access = getInternal(off, arrayPos);
        arrayPos = -1;
        if (access.skip(deltaCycle, epsCycle)) {
          if (listener != null) {
            listener.skippingHandledEdge(uniqueID, access.ii, false, this);
          }
          return;
        }
        final long curr = access.getDataLong();
        final EncapsulatedAccess prevAccess = internals_prev[off];
        prevAccess.offset = access.offset;
        final long prev = prevAccess.getDataLong();
        if ((prev != 1) || (curr != 0)) {
          if (listener != null) {
            listener.skippingNotAnEdge(uniqueID, access.ii, false, this);
          }
          return;
        }
        access.setLastUpdate(deltaCycle, epsCycle);
        break;
      }
      case isRisingEdge: {
        final int off = f.arg1;
        final EncapsulatedAccess access = getInternal(off, arrayPos);
        arrayPos = -1;
        if (access.skip(deltaCycle, epsCycle)) {
          if (listener != null) {
            listener.skippingHandledEdge(uniqueID, access.ii, true, this);
          }
          return;
        }
        final long curr = access.getDataLong();
        final EncapsulatedAccess prevAccess = internals_prev[off];
        prevAccess.offset = access.offset;
        final long prev = prevAccess.getDataLong();
        if ((prev != 0) || (curr != 1)) {
          if (listener != null) {
            listener.skippingNotAnEdge(uniqueID, access.ii, true, this);
          }
          return;
        }
        access.setLastUpdate(deltaCycle, epsCycle);
        break;
      }
      case posPredicate: {
        final int off = f.arg1;
        final EncapsulatedAccess access = getInternal(off, arrayPos);
        arrayPos = -1;
        // If data is not from this deltaCycle it was not
        // updated that means prior predicates failed
        if (!access.isFresh(deltaCycle, epsCycle)) {
          if (listener != null) {
            listener.skippingPredicateNotFresh(uniqueID, access.ii, true, this);
          }
          return;
        }
        if (ZERO.equals(access.getDataBig())) {
          if (listener != null) {
            listener.skippingPredicateNotMet(uniqueID, access.ii, true, access.getDataBig(), this);
          }
          return;
        }
        break;
      }
      case negPredicate: {
        final int off = f.arg1;
        final EncapsulatedAccess access = getInternal(off, arrayPos);
        arrayPos = -1;
        // If data is not from this deltaCycle it was not
        // updated that means prior predicates failed
        if (!access.isFresh(deltaCycle, epsCycle)) {
          if (listener != null) {
            listener.skippingPredicateNotFresh(uniqueID, access.ii, true, this);
          }
          return;
        }
        if (!ZERO.equals(access.getDataBig())) {
          if (listener != null) {
            listener.skippingPredicateNotMet(uniqueID, access.ii, false, access.getDataBig(), this);
          }
          return;
        }
        break;
      }
      case pushAddIndex:
        writeIndex[++arrayPos] = a.intValue();
        break;
      case writeInternal:
        final int off = f.arg1;
        final EncapsulatedAccess access = getInternal(off, -1);
        access.fillDataBig(arrayPos, writeIndex, a, deltaCycle, epsCycle);
        arrayPos = -1;
        break;
      }
      if (listener != null)
        if (stackPos >= 0) {
          if (f.popB) {
            listener.twoArgOp(uniqueID, b, f, (a), (stack[stackPos]), this);
          } else if (f.popA) {
            listener.oneArgOp(uniqueID, f, (a), (stack[stackPos]), this);
          } else {
            listener.noArgOp(uniqueID, f, (stack[stackPos]), this);
          }
        } else {
          listener.emptyStack(uniqueID, f, this);
        }
    }
    for (final EncapsulatedAccess encapsulatedAccess : outputAccess) {
      if (arrayPos != -1) {
        encapsulatedAccess.setOffset(writeIndex);
      }
      encapsulatedAccess.setDataBig(stack[0], deltaCycle, epsCycle);
      if (listener != null) {
        listener.writingResult(uniqueID, encapsulatedAccess.ii, stack[0], this);
      }
    }

    return;
  }

  public EncapsulatedAccess getInternal(int off, int arrayPos) {
    final EncapsulatedAccess res = internals[off];
    if (arrayPos != -1) {
      res.setOffset(writeIndex);
    }
    return res;
  }

  public static BigInteger srl(BigInteger l, int width, int shiftBy) {
    if (shiftBy == 0)
      return l;
    if (l.signum() >= 0)
      return l.shiftRight(shiftBy);
    final BigInteger opener = BigInteger.ONE.shiftLeft(width + 1);
    final BigInteger opened = l.subtract(opener);
    final BigInteger mask = opener.subtract(BigInteger.ONE).shiftRight(shiftBy + 1);
    final BigInteger res = opened.shiftRight(shiftBy).and(mask);
    return res;
  }
}
TOP

Related Classes of org.pshdl.interpreter.frames.BigIntegerFrame

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.