Пример #1
0
        /// <summary>
        /// List all PLA entries that trigger on a specific opcode
        /// If the opcode # (hex) was not given, dump that information for all opcodes (0-FF)
        /// </summary>
        private void MatchPLA(string arg)
        {
            int op = -1;

            if (!string.IsNullOrEmpty(arg))
            {
                op = ScanNumber(arg, 16);
                if (op < 0)
                {
                    return;
                }
            }
            for (int x = 0; x < 256; x++)
            {
                if (op >= 0 && x != op)
                {
                    continue;
                }
                ClassLog.Log(String.Format("Opcode: {0:X02} ", x));

                Byte          opcode = Convert.ToByte(x);
                List <string> m      = pla.TableMatch(modifier, opcode);

                foreach (var s in m)
                {
                    ClassLog.Log(s);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Dump opcode table in various ways.
        /// Returns a "selected" list of opcode numbers, that is, opcodes which were tagged by
        /// the optional input PLA table number given in arg parameter.
        /// </summary>
        public List <int> Table(ClassPlaEntry.Modifier modifier, int testNum, int arg)
        {
            ClassLog.Log(new string('-', 242));
            List <int> tagged = new List <int>();

            for (int y = 0; y < 16; y++)
            {
                string line = string.Format("{0:X} ", y);
                for (int x = 0; x < 16; x++)
                {
                    char          prefix = ' ';
                    byte          opcode = Convert.ToByte(y * 16 + x);
                    List <string> match  = TableMatch(modifier, opcode);
                    foreach (string oneMatch in match.Where(oneMatch => Convert.ToInt32(oneMatch.Substring(1, oneMatch.LastIndexOf(']') - 1)) == arg))
                    {
                        tagged.Add(y * 16 + x);
                        prefix = '*';
                    }
                    string entry = "";

                    //===============================================================================
                    // Table 0 - Show the number of PLA entries that match each opcode
                    //===============================================================================
                    if (testNum == 0)
                    {
                        entry = string.Join(",", match);
                        if (match.Count == 0)
                        {
                            entry = ".";
                        }
                        if (match.Count > 1)
                        {
                            entry = "[" + match.Count + "]";
                        }
                    }

                    //===============================================================================
                    // Table 1 - For each opcode, show all PLA entries that trigger
                    //===============================================================================
                    if (testNum == 1)
                    {
                        foreach (string oneMatch in match)
                        {
                            string n = oneMatch.Substring(1, oneMatch.LastIndexOf(']') - 1);
                            entry += n + ",";
                        }
                        entry = entry.TrimEnd(',');
                    }

                    // -------------------------------------------
                    if (entry.Length > 12)
                    {
                        entry = entry.Substring(0, 12);
                    }
                    line += string.Format(" |{0}{1,-12}", prefix, entry);
                }
                ClassLog.Log(line);
            }
            return(tagged);
        }
Пример #3
0
        /// <summary>
        /// This is the main program's startup function
        /// </summary>
        public void OnStart()
        {
            ClassLog.Log("PLA Checker Tool  Copyright (C) 2014  Goran Devic");
            ClassLog.Log("This program comes with ABSOLUTELY NO WARRANTY");
            ClassLog.Log("This is free software and you are welcome to redistribute it under certain conditions; for details see GPLv3 license.");
            ClassLog.Log("---------------------------------------------------------------------------------------------------------------------");

            // Load the PLA table from a text file.
            String plaFile = Properties.Settings.Default.plaFileName;

            if (!pla.Load(plaFile))
            {
                ClassLog.Log("*** Error loading the master input PLA source table ***");
                ClassLog.Log("Click on File -> Load PLA table... and select a resource file z80-pla.txt");
                return;
            }

            // Load opcode tables from a previously selected directory
            // We use only IX variation tables since IY's are the same
            String opFile = Properties.Settings.Default.opcodeDir;
            char   p      = Path.DirectorySeparatorChar;

            tableXX__.Load(opFile + p + "opcodes-xx.txt", 0);
            tableCBXX.Load(opFile + p + "opcodes-cb-xx.txt", 2);
            tableEDXX.Load(opFile + p + "opcodes-ed-xx.txt", 2);
            tableDDXX.Load(opFile + p + "opcodes-dd-xx.txt", 2);
            tableDDCB.Load(opFile + p + "opcodes-dd-cb.txt", 7);

            ClassLog.Log(Command("?"));
        }
Пример #4
0
 /// <summary>
 /// Dumps the opcode table in a table format
 /// The opcode numbers in the list t will be tagged (marked with *)
 /// </summary>
 public void Dump(List <int> t)
 {
     ClassLog.Log(new string('-', 242));
     for (int y = 0; y < 16; y++)
     {
         string line = string.Format("{0:X} ", y);
         for (int x = 0; x < 16; x++)
         {
             string opcode = "";
             if (op.ContainsKey(y * 16 + x))
             {
                 opcode = op[y * 16 + x];
             }
             if (opcode.Length > 12)
             {
                 opcode = opcode.Substring(0, 12);
             }
             char tag = ' ';
             if (t.Contains(y * 16 + x))
             {
                 tag = '*';
             }
             line += string.Format(" |{0}{1,-12}", tag, opcode);
         }
         ClassLog.Log(line);
     }
 }
Пример #5
0
 /// <summary>
 /// Dumps the content of the entire PLA table
 /// </summary>
 public void Dump()
 {
     ClassLog.Log("Content of the PLA table:");
     foreach (var p in pla.Where(p => !p.IsDuplicate()))
     {
         ClassLog.Log(p.Raw);
     }
 }
Пример #6
0
        /// <summary>
        /// User clicked on the Redo button: repeat the command
        /// </summary>
        private void BtRedoClick(object sender, EventArgs e)
        {
            ClassLog.Log(string.Format("{0}>>> {1}", commands.Count, commands[commands.Count - 1]));
            string response = Command(commands[commands.Count - 1]);

            if (!string.IsNullOrEmpty(response))
            {
                ClassLog.Log(response);
            }
        }
Пример #7
0
        /// <summary>
        /// Generates a Verilog module with the PLA logic
        /// </summary>
        public void GenVerilogPla()
        {
            string max    = (pla.Count() - 1).ToString();
            string module = "";

            module += @"//=====================================================================================" + Environment.NewLine;
            module += @"// This file is automatically generated by the z80_pla_checker tool. Do not edit!      " + Environment.NewLine;
            module += @"//=====================================================================================" + Environment.NewLine;
            module += @"module pla_decode" + Environment.NewLine;
            module += @"(" + Environment.NewLine;
            module += @"    input wire [6:0] prefix," + Environment.NewLine;
            module += @"    input wire [7:0] opcode," + Environment.NewLine;
            module += @"    output wire [" + max + ":0] pla" + Environment.NewLine;
            module += @");" + Environment.NewLine;
            module += @"" + Environment.NewLine;

            foreach (var p in pla)
            {
                if (p.IsDuplicate() || NotUsedPla.Contains(p.N))
                {
                    continue;
                }

                String bitstream = p.GetBitstream();
                module += string.Format(@"assign pla[{0,3}] = (({{prefix[6:0], opcode[7:0]}} & 15'b{1}) == 15'b{2}) ? 1'b1 : 1'b0;   // {3}",
                                        p.N,
                                        bitstream.Replace('0', '1').Replace('X', '0'), // Create "AND" mask
                                        bitstream.Replace('X', '0'),                   // Create a value to compare to
                                        p.Comment) + Environment.NewLine;
            }

            // List all PLA entries that are not used
            module += @"" + Environment.NewLine;
            module += @"// Entries not used by our timing matrix" + Environment.NewLine;
            foreach (var n in NotUsedPla)
            {
                module += string.Format(@"assign pla[{0,3}] = 1'b0;   // {1}", n, pla[n].Comment) + Environment.NewLine;
            }

            // List all PLA entries that are ignored
            module += @"" + Environment.NewLine;
            module += @"// Duplicate entries" + Environment.NewLine;
            foreach (var p in pla)
            {
                if (p.IsDuplicate())
                {
                    module += string.Format(@"assign pla[{0,3}] = 1'b0;   // {1}", p.N, p.Comment) + Environment.NewLine;
                }
            }

            module += @"" + Environment.NewLine;
            module += @"endmodule" + Environment.NewLine;

            ClassLog.Log(module);
        }
Пример #8
0
 private static int ScanNumber(string arg, int baseValue)
 {
     try
     {
         return(Convert.ToInt32(arg, baseValue));
     }
     catch (Exception ex)
     {
         ClassLog.Log(ex.Message + ": " + arg);
         return(-1);
     }
 }
Пример #9
0
        /// <summary>
        /// Update button state after the internal flag state change
        /// </summary>
        private void UpdateButtons()
        {
            btIX0.Checked  = (modifier & ClassPlaEntry.Modifier.IXY0) != 0;
            btIX1.Checked  = (modifier & ClassPlaEntry.Modifier.IXY1) != 0;
            btHALT.Checked = (modifier & ClassPlaEntry.Modifier.NHALT) != 0;
            btALU.Checked  = (modifier & ClassPlaEntry.Modifier.ALU) != 0;
            btXX.Checked   = (modifier & ClassPlaEntry.Modifier.XX) != 0;
            btCB.Checked   = (modifier & ClassPlaEntry.Modifier.CB) != 0;
            btED.Checked   = (modifier & ClassPlaEntry.Modifier.ED) != 0;

            ClassLog.Log("Set modifier to " + modifier);
        }
Пример #10
0
        /// <summary>
        /// Query PLA table string given as a vector of 0's and 1's
        /// This vector is coped from a ModelSim simulation run. The function will decode PLA string
        /// into a set of PLA entries that are being triggered ("1")
        /// </summary>
        public void QueryPla(String bits)
        {
            int max = pla.Count();

            if (bits.Count() != max)
            {
                ClassLog.Log("Invalid PLA length - the bit array should be " + max + " and it is " + bits.Count());
                return;
            }
            for (int i = 0; i < max; i++)
            {
                if (bits[max - i - 1] == '1')
                {
                    ClassLog.Log(string.Format(@"pla[{0,3}] = 1;   // {1}", pla[i].N, pla[i].Comment));
                }
            }
        }
Пример #11
0
        public bool Ignored = false;                // This entry can optionally be ignored

        /// <summary>
        /// PLA entry class constructor
        /// Accepts the init string which should contain a line from the PLA master table.
        /// Various fields from that line are read into this class.
        /// </summary>
        public bool Init(string init)
        {
            try
            {
                Raw = init;
                char[]   delimiterChars = { '\t' };
                string[] w = init.Split(delimiterChars);

                // Example of an input line:
                // w[0]                    w[1] w[2] w[3]     w[4]
                // ....1.. 1.1........1.11.  D   63  00xxx110 ld r,*

                // Mark a duplicate
                duplicate = w[1].Contains("D");

                // Read the 7 bits of the prefix
                for (int i = 0; i < 7; i++)
                {
                    if (w[0][6 - i] == '1')
                    {
                        prefix |= (1 << i);
                    }
                }

                // Read 16 bits of the opcode mask
                for (int i = 0; i < 16; i++)
                {
                    if (w[0][23 - i] == '1')
                    {
                        opcode |= (1 << i);
                    }
                }

                N       = Convert.ToInt32(w[2]);
                Comment = w[4];

                return(true);
            }
            catch (Exception ex)
            {
                ClassLog.Log("ClassPlaEntry: Can't parse line: " + init);
                ClassLog.Log(ex.Message);
            }
            return(false);
        }
Пример #12
0
        /// <summary>
        /// List all opcodes that trigger on a given PLA table index
        /// </summary>
        private void MatchOpcodes(ClassPlaEntry.Modifier modifier, string arg)
        {
            int index = ScanNumber(arg, 10);

            if (index < 0)
            {
                return;
            }
            List <string> m = pla.MatchPLA(modifier, index);

            if (m.Count == 0)
            {
                return;
            }
            ClassLog.Log(String.Format("PLA Entry: {0}  Modifier: {1}", index, modifier));
            foreach (var s in m)
            {
                ClassLog.Log(s);
            }
        }
Пример #13
0
        /// <summary>
        /// Implements a simple command history
        /// </summary>
        private void TextOpKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                // Mark the handled flag so this key won't be processed.
                e.Handled = true;
                string cmd = textOp.Text.Trim();
                if (cmd.Length > 0)
                {
                    commands.Add(cmd);
                    btRedo.Enabled = true;
                    ClassLog.Log(string.Format("{0}>>> {1}", commands.Count, cmd));
                    string response = Command(textOp.Text);
                    if (!string.IsNullOrEmpty(response))
                    {
                        ClassLog.Log(response);
                    }

                    commandsBrowseIndex = commands.Count;
                    textOp.Text         = "";
                }
                textOp.Focus();
            }
            if (e.KeyCode == Keys.PageUp && commandsBrowseIndex > 0)
            {
                commandsBrowseIndex--;
                textOp.Text = commands[commandsBrowseIndex];
                e.Handled   = true;
            }
            if (e.KeyCode == Keys.PageDown && commandsBrowseIndex < commands.Count - 1)
            {
                commandsBrowseIndex++;
                textOp.Text = commands[commandsBrowseIndex];
                e.Handled   = true;
            }
            if (e.KeyCode == Keys.Escape)
            {
                textOp.Text = "";
                e.Handled   = true;
            }
        }
Пример #14
0
        /// <summary>
        /// Loads an opcode table from a text file
        /// </summary>
        public void Load(string filename, int xxindex)
        {
            ClassLog.Log("Loading opcode table: " + filename);

            try
            {
                string[] lines = File.ReadAllLines(filename);
                op.Clear();
                foreach (string line in lines)
                {
                    string hex   = line.Substring(xxindex, 2);
                    string instr = line.Substring(12);
                    int    xx    = Convert.ToInt32(hex, 16);
                    op[xx] = instr;
                }
            }
            catch (Exception ex)
            {
                ClassLog.Log(ex.Message);
            }
        }
Пример #15
0
        /// <summary>
        /// Given the PLA ID, return a list of all opcodes that trigger it
        /// </summary>
        public List <string> MatchPLA(ClassPlaEntry.Modifier modifier, int id)
        {
            var m = new List <string>();

            // Find the pla with a given index
            foreach (ClassPlaEntry p in pla)
            {
                if (p.N == id)
                {
                    // For each possible opcode...
                    for (int i = 0; i < 256; i++)
                    {
                        String match = p.Match(modifier, Convert.ToByte(i));
                        if (!string.IsNullOrEmpty(match))
                        {
                            m.Add(string.Format("{0:X02} => {1}", i, match));
                        }
                    }
                    return(m);
                }
            }
            ClassLog.Log("Non-existent PLA index");
            return(m);
        }
Пример #16
0
        /// <summary>
        /// Read the master PLA table from a text file
        /// </summary>
        public bool Load(string filename)
        {
            // Read each line of the file into a string array. Each element
            // of the array is one line of the file.
            ClassLog.Log("Loading PLA: " + filename);

            try
            {
                string[] lines = File.ReadAllLines(filename);
                pla.Clear();
                foreach (string line in lines)
                {
                    if (line[0] == '#')
                    {
                        continue;
                    }
                    var p = new ClassPlaEntry();
                    if (p.Init(line))
                    {
                        pla.Add(p);
                    }
                }
            }
            catch (Exception ex)
            {
                ClassLog.Log(ex.Message);
                return(false);
            }
            ClassLog.Log(string.Format("Total {0} PLA lines", pla.Count()));

            ////============================================================
            //// Ignore duplicate PLA entries
            //IgnoredPla.Add(98);     // Duplicate of 37
            //IgnoredPla.Add(94);     // Duplicate of 12 and 18
            //IgnoredPla.Add(93);     // Duplicate of 11 and 19
            //IgnoredPla.Add(90);     // Duplicate of 26
            //IgnoredPla.Add(87);     // Duplicate of 83
            //IgnoredPla.Add(71);     // Duplicate of 25
            //IgnoredPla.Add(63);     // Duplicate of 17
            //IgnoredPla.Add(60);     // Duplicate of 15
            //IgnoredPla.Add(41);     // Duplicate of 3
            //IgnoredPla.Add(36);     // Duplicate of 8
            //IgnoredPla.Add(32);     // Duplicate of 4
            //IgnoredPla.Add(19);     // Duplicate of 11 and 93
            //IgnoredPla.Add(18);     // Duplicate of 12 and 94

            ////============================================================
            //// Special signals (not instructions)
            //IgnoredPla.Add(91);     // This signal goes along block IN/OUT instructions.
            //IgnoredPla.Add(75);     // This signal specifies a decrement operation for PLA 53, 66 and 105. Otherwise, it is an increment.
            //IgnoredPla.Add(55);     // This signal specifies (HL) addressing for all CB-table instructions, PLA entries 70, 72, 73, 74.
            //IgnoredPla.Add(44);     // This signal specifies a regular CB opcode (ignoring IX/IY).
            //IgnoredPla.Add(33);     // This signal specifies whether the register is being loaded or stored to memory for PLA entry 31.
            //IgnoredPla.Add(28);     // This signal specifies the OUT operation for PLA 37. Otherwise, it is operation.
            //IgnoredPla.Add(27);     // This signal goes along individual IN/OUT instructions in the ED table.
            //IgnoredPla.Add(16);     // This signal specifies a PUSH operation for PLA23. Otherwise, it is a POP operation.
            //IgnoredPla.Add(13);     // This signal specifies whether the value is being loaded or stored for PLA entries 8, 30 and 38.
            //IgnoredPla.Add(0);      // This signal specifies *not* to repeat block instructions.

            ////============================================================
            //// Ignore our own reserved entries
            //IgnoredPla.Add(107);
            //IgnoredPla.Add(106);

            //============================================================
            // Remove op-bits so we the output is more readable
            IgnoredPla.Add(99);
            IgnoredPla.Add(100);
            IgnoredPla.Add(101);
            IgnoredPla.Add(102);
            IgnoredPla.Add(103);
            IgnoredPla.Add(104);

            // Remove ALU operation entries so the output is more readable
            IgnoredPla.Add(88);
            IgnoredPla.Add(86);
            IgnoredPla.Add(85);
            IgnoredPla.Add(84);
            IgnoredPla.Add(80);
            IgnoredPla.Add(79);
            IgnoredPla.Add(78);
            IgnoredPla.Add(76);

            //============================================================
            // Signals not used in the Timings spreadsheet. For those, PLA table entries are not generated.
            // This list is used only when generating the PLA table.
            NotUsedPla.Add(67);       // This signal defines a specific in(), but we use in/out pla[27] + pla[34]
            NotUsedPla.Add(62);       // This signal is issued for all CB opcodes
            NotUsedPla.Add(54);       // This signal specifies every CB with IX/IY
            NotUsedPla.Add(22);       // This signal specifies CB prefix w/o IX/IY
            NotUsedPla.Add(14);       // This signal specifies a decrement operation for PLA 9. Otherwise, it is an increment.
            NotUsedPla.Add(4);        // This signal goes along instructions that access I and R register (PLA 57 and 83).

            //============================================================
            // Mark all PLA entries we decided to ignore
            foreach (var p in pla)
            {
                if (IgnoredPla.Contains <int>(p.N))
                {
                    p.Ignored = true;
                }
            }
            return(true);
        }
Пример #17
0
        /// <summary>
        /// Execute a command
        /// </summary>
        private string Command(string cmd)
        {
            try
            {
                string[] tokens = cmd.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                if (tokens.Length == 0)
                {
                    return("");
                }
                switch (tokens[0])
                {
                case "?":
                case "h":
                    return(Environment.NewLine +
                           "p         - Dump the content of the PLA table" + Environment.NewLine +
                           "p [#]     - For a given PLA entry # (dec) show opcodes that trigger it" + Environment.NewLine +
                           "m [#]     - Match opcode # (hex) with a PLA entry (or match 0-FF)" + Environment.NewLine +
                           "g         - Generate a Verilog PLA module" + Environment.NewLine +
                           "t [#] <#> - Show opcode table in various ways" + Environment.NewLine +
                           "            0 - Display number of PLA entries that trigger on each opcode" + Environment.NewLine +
                           "            1 - For each opcode, display all PLA entry numbers that trigger" + Environment.NewLine +
                           "            <#> - Add a * to opcodes for which the specified PLA entry triggers" + Environment.NewLine +
                           "q 101000... Query PLA table string" + Environment.NewLine +
                           "c         - Clear the screen");

                case "p": if (tokens.Length > 1)
                    {
                        MatchOpcodes(modifier, tokens[1]);
                    }
                    else
                    {
                        pla.Dump();
                    }
                    break;

                case "m": MatchPLA(tokens.Length > 1 ? tokens[1] : "");
                    break;

                case "g": pla.GenVerilogPla();
                    break;

                case "c": BtClearClick(null, null);
                    break;

                case "t":
                {
                    int arg1 = 0, arg2 = -1;
                    if (tokens.Length > 1)
                    {
                        arg1 = ScanNumber(tokens[1], 10);
                    }
                    if (tokens.Length > 2)
                    {
                        arg2 = ScanNumber(tokens[2], 10);
                    }
                    if (arg1 == 0 || arg1 == 1)
                    {
                        List <int> tagged = pla.Table(modifier, arg1, arg2);
                        DumpOpcodeTable(tagged);
                    }
                    else
                    {
                        ClassLog.Log("Invalid table number!");
                    }
                }
                break;

                case "q": pla.QueryPla(tokens[1].Trim());
                    break;

                default:
                    return("?");
                }
            }
            catch (Exception ex)
            {
                ClassLog.Log("Error: " + ex.Message);
            }
            return(string.Empty);
        }