public static String GetEntrypointsString(Microprogram microprogram, Boolean generateDebugInfo = false)
        {
            String entrypoints   = "";
            int    addressLength = Convert.ToString(microprogram.MicroprogramLength - 1, 2).Length; //Bit length of entrypoint addresses

            for (int i = 0; i < Math.Pow(2, microprogram.OpcodeWidth); i++)
            {
                if (microprogram.InstructionEntrypoints.ContainsKey(i))
                {
                    String   symbol = microprogram.InstructionEntrypoints[i];
                    Sequence sequence;
                    if ((sequence = microprogram[symbol] as Sequence) == null)
                    {
                        throw new MicroassemblerWriteException($"Symbol {symbol} bound to entrypoint {i} does not exist");
                    }
                    if (sequence.IsMacro)
                    {
                        throw new MicroassemblerWriteException($"Symbol {symbol} bound to entrypoint {i} is a macro (macros cannot be bound to entrypoints)");
                    }
                    entrypoints += Convert.ToString(sequence.Address, 2).PadLeft(addressLength, '0');
                    if (generateDebugInfo)
                    {
                        entrypoints += $" //Instruction Entrypoint {i} at sequence {symbol} (address {sequence.Address})";
                    }
                    entrypoints += "\n";
                }
                else
                {
                    entrypoints += new String('0', addressLength) + ((generateDebugInfo) ? $" //Instruction entrypoint {i} is unused\n" : "\n");
                }
            }


            return(entrypoints);
        }
        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);
        }
        public static void WriteMicroprogram(Microprogram microprogram, List <Sequence> placedSequences, String path, Boolean generateDebugInfo = false)
        {
            String       program     = GetMicroprogramString(microprogram, placedSequences, generateDebugInfo);
            String       entrypoints = GetEntrypointsString(microprogram, generateDebugInfo);
            StreamWriter writer      = new StreamWriter(path + "/Microprogram");

            writer.Write(program);
            writer.Dispose();
            writer = new StreamWriter(path + "/Entrypoints");
            writer.Write(entrypoints);
            writer.Dispose();
        }
        public static String GetMicroprogramString(Microprogram microprogram, List <Sequence> placedSequences, Boolean generateDebugInfo = false)
        {
            int    filled  = 0;
            String program = "";

            foreach (Sequence sequence in placedSequences)
            {
                if (generateDebugInfo)
                {
                    program += $"//Sequence '{sequence.Symbol}' at address {sequence.Address}\n";
                }
                BitArray[] steps = ProcessSequence(sequence, microprogram);
                filled += steps.Length;
                steps.EachIndex((s, i) =>
                {
                    program += s.ToBitString();
                    if (generateDebugInfo)
                    {
                        String labels = GetLocalLabels(sequence, i);
                        if (!String.IsNullOrEmpty(labels))
                        {
                            program += $"   //{labels} (address {sequence.Address + i})";
                        }
                    }
                    program += "\n";
                });
                if (generateDebugInfo)
                {
                    program += "\n";
                }
            }
            //Fill the rest of the program with the defined empty step
            if (generateDebugInfo)
            {
                program += $"//Empty space ({microprogram.MicroprogramLength - filled} unused addresses)\n";
            }
            String emptyStep = ProcessStep(microprogram.EmptyAssertion, microprogram).ToBitString();

            for (int i = 0; i < microprogram.MicroprogramLength - filled; i++)
            {
                program += emptyStep + "\n";
            }
            return(program);
        }
Пример #5
0
        public List <Sequence> PlaceMicroprogram(Microprogram microprogram) //Assign each sequence an absolute starting address and return a list of all sequences in order.  Assign the fetch sequence to address 0
        {
            int             currAddress     = 0;
            List <Sequence> placedSequences = new List <Sequence>();
            Sequence        fetchSequence   = microprogram[microprogram.FetchEntrypoint] as Sequence;

            if (fetchSequence == null)
            {
                throw new MicroassemblerLinkException($"Fetch sequence '{microprogram.FetchEntrypoint}' was not found");
            }
            if (fetchSequence.IsMacro)
            {
                throw new MicroassemblerLinkException($"Fetch sequence '{microprogram.FetchEntrypoint}' is defined as a Macro");
            }
            fetchSequence.Address = 0;
            RecurseAssignBaseAddress(fetchSequence, 0);
            currAddress += fetchSequence.Steps.Count;
            placedSequences.Add(fetchSequence);
            foreach (KeyValuePair <String, Object> kv in microprogram.Symbols)
            {
                if (kv.Value is Sequence && kv.Value != fetchSequence)
                {
                    Sequence sequence = kv.Value as Sequence;
                    if (sequence.IsMacro)
                    {
                        continue;                   //Do NOT place macros
                    }
                    sequence.Address = currAddress; //Assign sequence base address
                    RecurseAssignBaseAddress(sequence, currAddress);
                    currAddress += sequence.Steps.Count;
                    placedSequences.Add(sequence);
                }
            }
            if (currAddress > microprogram.MicroprogramLength - 1)
            {
                throw new MicroassemblerLinkException($"Placed microprogram is of length {currAddress + 1} which exceeds the maximum length of {microprogram.MicroprogramLength}");
            }
            return(placedSequences);
        }
Пример #6
0
        static void Main(string[] args)
        {
            Console.WriteLine(new BitMask(62, 0).ToLongMask());

            StreamReader reader = new StreamReader("Microprogram.mal");
            String       file   = reader.ReadToEnd();

            reader.Dispose();
            MicroprogramParser   parser       = new MicroprogramParser();
            Microprogram         microprogram = parser.ParseProgram(file);
            MicroprogramExpander expander     = new MicroprogramExpander();

            expander.ExpandMicroprogram(microprogram);
            MicroprogramLinker linker          = new MicroprogramLinker();
            List <Sequence>    placedSequences = linker.PlaceMicroprogram(microprogram);

            linker.ResolveSymbols(microprogram, placedSequences);
            MicroprogramFileWriter.WriteMicroprogram(microprogram, placedSequences, System.IO.Directory.GetCurrentDirectory(), true);



            Console.WriteLine();
        }
        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);
        }
Пример #8
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;
                }
            }
        }
 public static BitArray[] ProcessSequence(Sequence sequence, Microprogram microprogram)
 {
     BitArray[] arrays = new BitArray[sequence.Steps.Count];
     sequence.Steps.EachIndex((s, i) => arrays[i] = ProcessStep(s, microprogram));
     return(arrays);
 }
Пример #10
0
        public Microprogram ParseProgram(String program)
        {
            Microprogram = new Microprogram();
            Enumerator   = Tokenizer.Tokenize(program);
            if (Enumerator == null)
            {
                return(null);
            }
            while (Enumerator.HasToken())
            {
                Token token = Enumerator.Current;
                Enumerator.Advance();
                if (token.TokenType == TokenType.Word)
                {
                    String keyword = (String)token.Value;
                    switch (keyword.ToLower())
                    {
                    case "config":
                        if (!ProcessConfigs())
                        {
                            return(null);
                        }
                        break;

                    case "const":
                        if (!ProcessConstant())
                        {
                            return(null);
                        }
                        break;

                    case "control":
                        if (!ProcessControlWordLabel())
                        {
                            return(null);
                        }
                        break;

                    case "sequence":
                        if (!ProcessSequence())
                        {
                            return(null);
                        }
                        break;

                    case "macro":
                        if (!ProcessMacro())
                        {
                            return(null);
                        }
                        break;

                    case "empty":
                        if (!ParseEmpty())
                        {
                            return(null);
                        }
                        break;

                    case "entrypoints":
                        if (!ParseEntrypoints())
                        {
                            return(null);
                        }
                        break;

                    default:
                        throw new MicroassemblerParseException(token, "Keyword expected");
                    }
                }
                else
                {
                    throw new MicroassemblerParseException(token, "Keyword expected");
                }
            }
            //Config sanity checks
            if (Microprogram.MicroprogramLength <= 0)
            {
                throw new MicroassemblerParseException($"The microprogram length must be greater than zero");
            }
            if (Microprogram.OpcodeWidth <= 0)
            {
                throw new MicroassemblerParseException($"The opcode width must be greater than zero");
            }
            if (Microprogram.ControlWordWidth <= 0)
            {
                throw new MicroassemblerParseException($"The control word width must be greater than zero");
            }
            if (Microprogram.BankSelectorMask.Length <= 0)
            {
                throw new MicroassemblerParseException($"The bank selector width must be greater than zero");
            }
            if (Microprogram.BankSelectorMask.Length + 1 >= Microprogram.ControlWordWidth)
            {
                throw new MicroassemblerParseException($"Control word width of {Microprogram.ControlWordWidth} is invalid, as the bank selector has a width of {Microprogram.BankSelectorMask.Length}");
            }
            //Check control word label lengths
            foreach (ControlWordLabel cw in Microprogram.ControlWordLabels.Values)
            {
                if (cw.Mask.Length <= 0)
                {
                    throw new MicroassemblerParseException($"Control word label {cw.Name} must have a length that is geater than zero");
                }
                if (cw.Mask.Length + Microprogram.BankSelectorMask.Length > Microprogram.ControlWordWidth)
                {
                    throw new MicroassemblerParseException($"Control word label {cw.Name} exceeds the maximum control word width of {Microprogram.ControlWordWidth - Microprogram.BankSelectorMask.Length}");
                }
            }
            return(Microprogram);
        }