예제 #1
0
 public void RecurseAssignBaseAddress(SymbolContainer container, int address) //Recursively assign a sequence base address to all symbols
 {
     foreach (KeyValuePair <String, Object> kv in container.Symbols)
     {
         Object o = kv.Value;
         if (o is SequenceLabel)
         {
             (o as SequenceLabel).BaseAddress = address;
         }
         if (o is SymbolContainer)
         {
             RecurseAssignBaseAddress(o as SymbolContainer, address);
         }
     }
 }
        public static String GetLocalLabels(SymbolContainer container, int labelAddress, String parentSymbol = "")
        {
            String labels = "";

            foreach (KeyValuePair <String, Object> kv in container.Symbols)
            {
                if (kv.Value is SymbolContainer)
                {
                    labels += GetLocalLabels(kv.Value as SymbolContainer, labelAddress, (parentSymbol.Length > 0) ? parentSymbol + "." + kv.Key : kv.Key);
                }
                else if (kv.Value is SequenceLabel && (kv.Value as SequenceLabel).LocalAddress == labelAddress)
                {
                    labels += $" ::{((parentSymbol.Length > 0) ? parentSymbol + "." : "") + kv.Key}:: |";
                }
            }
            return(labels);
        }
 public void RecurseOffset(SymbolContainer container, int startAddr, int offset)
 {
     foreach (KeyValuePair <String, Object> kv in container.Symbols)
     {
         Object o = kv.Value;
         if (o is SequenceLabel)
         {
             SequenceLabel ol = o as SequenceLabel;
             if (ol.LocalAddress > startAddr)
             {
                 ol.LocalAddress += offset;
             }
         }
         if (o is SymbolContainer)
         {
             RecurseOffset(o as SymbolContainer, startAddr, offset);
         }
     }
 }
        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);
        }