public static BitArray ProcessStep(SequenceStep step, Microprogram microprogram)
        {
            if (step.Type == SequenceStepType.MacroReference)
            {
                throw new MicroassemblerWriteException($"Unexpanded macro found on line {step.Line}");
            }
            SequenceAssertion assertion = step as SequenceAssertion;
            BitArray          array     = new BitArray((int)microprogram.ControlWordWidth);

            array[microprogram.BankSelectorMask] = (ulong)assertion.Bank;
            int bankOffset = microprogram.BankSelectorMask.Length;

            foreach (KeyValuePair <ControlWordLabel, Object> signal in assertion.AssertedSignals)
            {
                if (!(signal.Value is long))
                {
                    throw new MicroassemblerWriteException($"Invalid/unresolved symbol {signal.Value} in assertion on line {assertion.Line}");
                }
                long value = (long)signal.Value;
                if (value > (long)signal.Key.Mask.MaxValue)
                {
                    Console.WriteLine($"Warning: Asserted signal {signal.Key.Name} on line {assertion.Line} has a maximum value of {signal.Key.Mask.MaxValue} (actual assertion of {value} will be truncated)");
                }
                array[signal.Key.Mask, bankOffset] = (ulong)value;
            }
            return(array);
        }
Exemplo n.º 2
0
        public Boolean ParseEmpty()
        {
            SequenceAssertion assertion = ParseSequenceAssertion();

            Microprogram.EmptyAssertion = assertion;
            return(true);
        }
Exemplo n.º 3
0
        public SequenceAssertion ParseSequenceAssertion() //Parses an assertion statement
        {
            SequenceAssertion assertion = new SequenceAssertion();

            VerifySyntaxToken(TokenType.OpenBlock, "{");
            int startLine = Enumerator.Last.Line;

            assertion.Line = startLine;
            while (true)
            {
                if (!Enumerator.HasToken())
                {
                    throw new MicroassemblerParseException($"Unfinished assertion statement on line {startLine}");
                }
                Token token = Enumerator.Current;
                Enumerator.Advance();
                if (token.TokenType == TokenType.CloseBlock)
                {
                    break;
                }
                else if (token.TokenType == TokenType.Pair)
                {
                    Object labelName  = (token.Value as Object[])[0];
                    Object labelValue = (token.Value as Object[])[1];
                    if (!(labelName is String))
                    {
                        throw new MicroassemblerParseException($"Invalid assertion key on line {token.Line}");
                    }
                    if (!Microprogram.ControlWordLabels.ContainsKey(labelName.ToString()))
                    {
                        throw new MicroassemblerParseException($"Nonexistant control word label on line {token.Line}");
                    }
                    assertion.AddAssertion(Microprogram.ControlWordLabels[labelName.ToString()], labelValue);
                    if (Enumerator.HasNext() && Enumerator.Next.TokenType == TokenType.Pair)
                    {
                        VerifySyntaxToken(TokenType.ListDelimeter, ",");
                    }
                    if (Enumerator.HasNext() && Enumerator.Next.TokenType == TokenType.CloseBlock)
                    {
                        DiscardOptionalToken(TokenType.ListDelimeter, ",");
                    }
                }
                else
                {
                    throw new MicroassemblerParseException(token);
                }
            }

            if (assertion.AssertedSignals.Count > 0)
            {
                List <ControlWordLabel> overlaps = assertion.AssertedSignals.Where(signal1 => assertion.AssertedSignals.Any(signal2 => (!signal2.Equals(signal1) && signal1.Key.Mask.OverlapsWith(signal2.Key.Mask)))).Select(kv => kv.Key).ToList();
                if (overlaps.Count > 0)
                {
                    Console.WriteLine($"Warning: Assertion on line {startLine} contains overlapping signals: {String.Join(", ", overlaps.Select(o => o.Name))}");
                }
            }
            return(assertion);
        }
        public void ExpandMicroprogram(Microprogram microprogram) //Expands all macro references and resolves constants/macro variables
        {
            Microprogram = microprogram;
            Sequence sequence;

            do
            {
                sequence = microprogram.Symbols.Where(kv => ((kv.Value is Sequence) && (kv.Value as Sequence).Unexpanded && !(kv.Value as Sequence).IsMacro && (kv.Value as Sequence).Steps.Count > 0)).Select(kv => (Sequence)kv.Value).FirstOrDefault(); //Get first unexpanded sequence
                if (sequence == null)
                {
                    break;
                }
                int macroAddr;
                for (macroAddr = 0; macroAddr < sequence.Steps.Count; macroAddr++)
                {
                    if (sequence.Steps[macroAddr].Type == SequenceStepType.MacroReference)
                    {
                        break;                                                                                                                                   //Find the first macro reference within the sequence
                    }
                }
                SequenceMacroReference mRef = sequence.Steps[macroAddr] as SequenceMacroReference;
                if (microprogram[mRef.Symbol] == null || !(microprogram[mRef.Symbol] is Sequence))
                {
                    throw new MicroassemblerExpansionException($"Macro {mRef.Symbol} referenced on line {mRef.Line} does not exist");
                }
                Sequence macro = (Sequence)Microprogram[mRef.Symbol];
                if (macro.Parameters.Count > mRef.Arguments.Count)
                {
                    throw new MicroassemblerExpansionException($"Macro reference on line {mRef.Line} provides {mRef.Arguments.Count} arguments, while the referenced macro has {macro.Parameters.Count} parameters");
                }
                List <SequenceStep> copiedSteps = macro.Steps.Select(s => (SequenceStep)s.Clone()).ToList();
                //Find a unique expansion symbol
                String expansionSymbol;
                int symNum = 0;
                do
                {
                    expansionSymbol = ((String.IsNullOrEmpty(mRef.ParentReference)) ? "_" : mRef.ParentReference + "._") + mRef.Symbol + "_" + symNum.ToString();
                    symNum++;
                }while (sequence[expansionSymbol] != null);
                //Recursively Offset all address symbols after the macro
                RecurseOffset(sequence, macroAddr, macro.Steps.Count - 1); //The macro call step is removed, so that is not counted as part of the offset
                //Create a container for symbols within the expanded macro and copy symbols from the original macro
                SymbolContainer expansionContainer = new SymbolContainer();
                macro.Symbols.ForEach(kv => expansionContainer.Symbols.Add(kv.Key, (kv.Value is ICloneable) ? (kv.Value as ICloneable).Clone() : kv.Value));
                sequence[expansionSymbol] = expansionContainer;
                expansionContainer.Symbols.ForEach(kv => OffsetObject(kv.Value, macroAddr));
                //Replace parameter references in copied steps with arguments, also add the expanded symbol name to any internal macro symbol references
                foreach (SequenceStep step in copiedSteps)
                {
                    if (step is SequenceMacroReference)
                    {
                        SequenceMacroReference stepRef = step as SequenceMacroReference;
                        if (stepRef.Symbol.Equals(mRef.Symbol))
                        {
                            throw new MicroassemblerExpansionException($"Caught recursive macro self-reference on line {stepRef.Line}");                                     //Sanity check
                        }
                        stepRef.Arguments       = stepRef.Arguments.Select(a => SubArgumentsAndSymbols(a, macro, mRef, expansionSymbol)).ToList();
                        stepRef.ParentReference = expansionSymbol;
                    }
                    else if (step is SequenceAssertion)
                    {
                        SequenceAssertion stepAssertion = step as SequenceAssertion;
                        stepAssertion.AssertedSignals = stepAssertion.AssertedSignals.Select(kv => new KeyValuePair <ControlWordLabel, Object>(kv.Key, SubArgumentsAndSymbols(kv.Value, macro, mRef, expansionSymbol))).ToDictionary(kv => kv.Key, kv => kv.Value);
                    }
                }
                //Remove macro reference and insert steps
                sequence.Steps.RemoveAt(macroAddr);
                sequence.Steps.InsertRange(macroAddr, copiedSteps);
            }while (sequence != null);
        }
Exemplo n.º 5
0
        public void ResolveSymbols(Microprogram microprogram, List <Sequence> placedSequences) //Resolve all symbol references to numeric values
        {
            foreach (Sequence sequence in placedSequences)
            {
                foreach (SequenceStep step in sequence.Steps)
                {
                    if (step is SequenceMacroReference)
                    {
                        throw new MicroassemblerLinkException($"Encountered unexpanded macro on line {step.Line}");
                    }
                    if (step is SequenceAssertion)
                    {
                        SequenceAssertion assertion = step as SequenceAssertion;
                        foreach (ControlWordLabel key in assertion.AssertedSignals.Keys.ToList())
                        {
                            Object value = assertion.AssertedSignals[key];
                            if (!(value is long))
                            {
                                String         symbol = value.ToString();
                                SymbolSelector sel    = SymbolSelector.TryParse(symbol);
                                if (sel != null)
                                {
                                    if (long.TryParse(sel.Symbol, out long intValue))
                                    {
                                        assertion.AssertedSignals[key] = (intValue & sel.Selector.ToLongMask()) >> sel.Selector.LowerBound;
                                    }
                                    else
                                    {
                                        symbol = sel.Symbol;
                                        Object resolvedSymbol = (sequence[symbol] != null) ? sequence[symbol] : microprogram[symbol];
                                        if (resolvedSymbol == null)
                                        {
                                            throw new MicroassemblerLinkException($"Symbol {symbol} referenced by assertion on line {assertion.Line} is not defined");
                                        }
                                        if (resolvedSymbol is ISymbolResolver)
                                        {
                                            resolvedSymbol = (resolvedSymbol as ISymbolResolver).Resolve();
                                        }
                                        if (!(resolvedSymbol is long))
                                        {
                                            throw new MicroassemblerLinkException($"Symbol {symbol} resolved to {resolvedSymbol}, all symbols should resolve to a number");
                                        }
                                        assertion.AssertedSignals[key] = ((long)resolvedSymbol & sel.Selector.ToLongMask()) >> sel.Selector.LowerBound;
                                    }
                                }
                                else
                                {
                                    Object resolvedSymbol = (sequence[symbol] != null) ? sequence[symbol] : microprogram[symbol];
                                    if (resolvedSymbol == null)
                                    {
                                        throw new MicroassemblerLinkException($"Symbol {symbol} referenced by assertion on line {assertion.Line} is not defined");
                                    }
                                    if (resolvedSymbol is ISymbolResolver)
                                    {
                                        resolvedSymbol = (resolvedSymbol as ISymbolResolver).Resolve();
                                    }
                                    if (!(resolvedSymbol is long))
                                    {
                                        throw new MicroassemblerLinkException($"Symbol {symbol} resolved to {resolvedSymbol}, all symbols should resolve to a number");
                                    }
                                    assertion.AssertedSignals[key] = resolvedSymbol;
                                }
                            }
                        }
                    }
                }
            }
            //Resolve empty step
            SequenceAssertion emptyAssertion = microprogram.EmptyAssertion;

            if (microprogram.EmptyAssertion == null)
            {
                throw new MicroassemblerLinkException("The empty/default sequence step is not defined");
            }
            foreach (ControlWordLabel key in emptyAssertion.AssertedSignals.Keys.ToList())
            {
                Object value = emptyAssertion.AssertedSignals[key];
                if (!(value is long))
                {
                    String symbol         = value.ToString();
                    Object resolvedSymbol = microprogram[symbol];
                    if (resolvedSymbol == null)
                    {
                        throw new MicroassemblerLinkException($"Symbol {symbol} referenced by assertion on line {emptyAssertion.Line} is not defined");
                    }
                    if (resolvedSymbol is ISymbolResolver)
                    {
                        resolvedSymbol = (resolvedSymbol as ISymbolResolver).Resolve();
                    }
                    emptyAssertion.AssertedSignals[key] = resolvedSymbol;
                }
            }
        }
Exemplo n.º 6
0
        public Sequence ParseSequence(Boolean isMacro) // Parses a sequence and return an object representation (used for both normal sequences and macros)
        {
            Sequence sequence = new Sequence()
            {
                IsMacro = isMacro
            };

            if (Enumerator.HasToken() && Enumerator.Current.TokenType == TokenType.ParenList)
            {
                if (!isMacro)
                {
                    throw new MicroassemblerParseException(Enumerator.Last, "Only macros can define a parameter list");
                }
                List <Object> parameters = (List <Object>)Enumerator.Current.Value;
                Enumerator.Advance();
                if (parameters.Where(p => !(p is String) || (p is String && ((String)p).Any(Char.IsWhiteSpace))).Any())
                {
                    throw new MicroassemblerParseException(Enumerator.Last, "Parameter definitions may only contain non-whitespace-delimited words");
                }
                sequence.Parameters.AddRange(parameters.Cast <String>());
            }
            VerifySyntaxToken(TokenType.OpenBlock, "{");
            String word = "";

            do
            {
                if (Enumerator.HasToken() && Enumerator.Current.TokenType == TokenType.CloseBlock)
                {
                    Enumerator.Advance();
                    break;
                }
                word = GetWordToken();
                if (word.StartsWith("::") && word.EndsWith("::"))
                {
                    String label = word.Substring(2, word.Length - 4);
                    sequence[label] = new SequenceLabel {
                        LocalAddress = sequence.Steps.Count
                    };
                }
                else if (Enumerator.HasToken() && Enumerator.Current.TokenType == TokenType.ParenList)
                {
                    List <Object> arguments = (List <Object>)Enumerator.Current.Value;
                    Enumerator.Advance();
                    SequenceMacroReference step = new SequenceMacroReference()
                    {
                        Arguments = arguments, Symbol = word, Line = Enumerator.Last.Line
                    };
                    sequence.Steps.Add(step);
                }
                else if (word.ToLower().Equals("assert"))
                {
                    SequenceAssertion step = ParseSequenceAssertion();
                    sequence.Steps.Add(step);
                }
                else
                {
                    throw new MicroassemblerParseException(Enumerator.Last);
                }
            }while (true);

            return(sequence);
        }