예제 #1
0
        /// <summary>
        /// Evaluate a terminal (wires are instant, NOT gates are not)
        /// </summary>
        public override bool Eval(bool quick)
        {
            // Trace through wires (do not allow infinite recursion)
            OpCodeTerminal next  = this;
            OpCodeTerminal final = this;
            int            max   = 32;

            while (next != null && next.Negate == OpState.Zero && --max >= 0)
            {
                final = next;
                next  = next.Expression.Expr as OpCodeTerminal;
            }

            // Calculate new value
            OpState oldState = State;

            State     = PrevState;
            PrevState = final.Expression.Expr.State ^ final.Negate;
            bool changed = PrevState != State || PrevState != oldState;

            // Wires are always quick (no time delay).
            if (final.Negate == OpState.Zero || quick)
            {
                State = PrevState;
            }
            return(changed);
        }
예제 #2
0
        public override OpCode DeepClone(OpCode.VisitTerminalsDelegate copyTerm)
        {
            OpCodeTerminal term = (OpCodeTerminal)MemberwiseClone();

            copyTerm(term);
            return(term);
        }
예제 #3
0
파일: Optimizer.cs 프로젝트: gosub-com/Bit
        /// <summary>
        /// Non-recursively remove identities:
        ///	    a+!a = 1
        ///	    a*!a = 0
        ///	    a+a = a
        ///	    a*a = a
        /// </summary>
        OpCode RemoveIdentityNR(OpCode op)
        {
            if (op.Operands == null)
            {
                return(op);
            }
            int identity = 0;

            if (op is OpCodeOr)
            {
                identity = 1;
            }
            else if (!(op is OpCodeAnd))
            {
                return(op);
            }

            for (int i = 0; i < op.Operands.Count; i++)
            {
                OpCodeTerminal t1 = op.Operands[i] as OpCodeTerminal;
                if (t1 == null)
                {
                    continue;
                }
                for (int j = i + 1; j < op.Operands.Count; j++)
                {
                    OpCodeTerminal t2 = op.Operands[j] as OpCodeTerminal;
                    if (t2 == null)
                    {
                        continue;
                    }

                    // Follow wires to their terminal value
                    OpCodeTerminal trTerm1 = TraceTerm(t1);
                    OpCodeTerminal trTerm2 = TraceTerm(t2);

                    // a+!a = 1
                    // a*!a = 0
                    if (trTerm1.Expression == trTerm2.Expression &&
                        (t1.Negate ^ t2.Negate) == OpState.One)
                    {
                        mIdentityToConst++;
                        return(new OpCodeConst(identity));
                    }
                    //	a+a = a
                    //	a*a = a
                    if (trTerm1.Expression == trTerm2.Expression &&
                        ((t1.Negate == OpState.Zero && t2.Negate == OpState.Zero) ||
                         (t1.Negate == OpState.One && t2.Negate == OpState.One)))
                    {
                        op.Operands.RemoveAt(j);
                        j--;  // Retry this operand
                        mIdentityToSelf++;
                    }
                }
            }
            return(op);
        }
예제 #4
0
        public override bool Equals(object obj)
        {
            OpCodeTerminal op = obj as OpCodeTerminal;

            if (op == null)
            {
                return(false);
            }
            return(Expression.Index == op.Expression.Index &&
                   Expression.Name == op.Expression.Name &&
                   Negate == op.Negate);
        }
예제 #5
0
파일: Optimizer.cs 프로젝트: gosub-com/Bit
        /// <summary>
        /// Scan assignment chain for the last expression
        /// (e.g. TraceTerm(a) on a = b, b = c, c = (x+c) returns c)
        /// </summary>
        OpCodeTerminal TraceTerm(OpCodeTerminal term)
        {
            int            tries = 8;
            OpCodeTerminal trace = term.Expression.Expr as OpCodeTerminal;

            while (trace != null && trace.Expression.Expr.Negate == OpState.Zero &&
                   --tries != 0)
            {
                term  = trace;
                trace = term.Expression.Expr as OpCodeTerminal;
            }
            return(term);
        }
예제 #6
0
파일: Optimizer.cs 프로젝트: gosub-com/Bit
        /// <summary>
        /// Embed wires and constant wires
        /// </summary>
        OpCode EmbedWires(List <OpCodeExpr> expressions, OpCode op, int minOpt)
        {
            // Recurse down the expression tree
            if (op.Operands != null)
            {
                for (int i = 0; i < op.Operands.Count; i++)
                {
                    op.Operands[i] = EmbedWires(expressions, op.Operands[i], minOpt);
                }
            }

            // Replace only terminal
            OpCodeTerminal term = op as OpCodeTerminal;

            if (term == null)
            {
                return(op);
            }

            // Replace wire expressions (if the wire doesn't point outside of minOpt)
            OpCodeTerminal wire = term.Expression.Expr as OpCodeTerminal;

            if (wire != null && term.Expression.Index >= minOpt)
            {
                // Replace this terminal with the wire's target
                // (i.e. follow the wire)
                term.Negate    ^= wire.Negate;
                term.Expression = wire.Expression;
                mWires++;
                return(term);
            }
            // Replace constant expressions
            OpCodeConst constTerm = term.Expression.Expr as OpCodeConst;

            if (constTerm != null)
            {
                constTerm.Eval(true);
                if (constTerm.State == OpState.Zero || constTerm.State == OpState.One)
                {
                    mConstWires++;
                    return(new OpCodeConst(((int)term.Negate ^ (int)constTerm.State) & 1));
                }
            }

            return(term);
        }
예제 #7
0
파일: Optimizer.cs 프로젝트: gosub-com/Bit
        /// <summary>
        /// Embed expressions that have only been used once
        /// </summary>
        OpCode EmbedSingleUses(List <OpCodeExpr> expressions, int index, OpCode op,
                               int[] timesUsed, int minOpt)
        {
            // Recurse down the expression tree
            if (op.Operands != null)
            {
                for (int i = 0; i < op.Operands.Count; i++)
                {
                    op.Operands[i] = EmbedSingleUses(expressions, index, op.Operands[i],
                                                     timesUsed, minOpt);
                }
            }

            // Embed terminal expressions that have only been used once,
            // and are within the optimization range, and are not this expression
            OpCodeTerminal term = op as OpCodeTerminal;

            if (term == null || timesUsed[term.Expression.Index] != 1 ||
                term.Expression.Index < minOpt ||
                index == term.Expression.Index)
            {
                return(op);
            }


            // Replace this terminal with the expression
            // (i.e. make it a sub-expression)
            OpCode newOp = expressions[term.Expression.Index].Expr;

            newOp.Negate ^= term.Negate;
            expressions[term.Expression.Index].Expr = null;
            expressions[term.Expression.Index]      = null;
            term.Expression = null;
            mEmbeddedSingletons++;
            return(newOp);
        }