OpenCores
URL https://opencores.org/ocsvn/a-z80/a-z80/trunk

Subversion Repositories a-z80

[/] [a-z80/] [trunk/] [tools/] [z80_pla_checker/] [source/] [ClassPLA.cs] - Blame information for rev 3

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 gdevic
´╗┐using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Linq;
5
 
6
namespace z80_pla_checker
7
{
8
    /// 
9
    /// This class defines a complete PLA table and operations on it
10
    /// 
11
    class ClassPla
12
    {
13
        /// 
14
        /// List of all PLA entries that we read from the input file
15
        /// 
16
        private readonly List pla = new List();
17
 
18
        /// 
19
        /// List of PLA entries which we want to ignore for various reasons
20
        /// 
21
        public List IgnoredPla = new List();
22
 
23
        /// 
24
        /// Returns the total number of PLA table entries
25
        /// 
26
        public int Count()
27
        {
28
            return pla.Count();
29
        }
30
 
31
        /// 
32
        /// Read the master PLA table from a text file
33
        /// 
34
        public bool Load(string filename)
35
        {
36
            // Read each line of the file into a string array. Each element
37
            // of the array is one line of the file.
38
            ClassLog.Log("Loading PLA: " + filename);
39
 
40
            try
41
            {
42
                string[] lines = File.ReadAllLines(filename);
43
                pla.Clear();
44
                foreach (string line in lines)
45
                {
46
                    if (line[0] == '#')
47
                        continue;
48
                    var p = new ClassPlaEntry();
49
                    if (p.Init(line))
50
                        pla.Add(p);
51
                }
52
            }
53
            catch (Exception ex)
54
            {
55
                ClassLog.Log(ex.Message);
56
                return false;
57
            }
58
            ClassLog.Log(string.Format("Total {0} PLA lines", pla.Count()));
59
 
60
            ////============================================================
61
            //// Ignore duplicate PLA entries
62
            //IgnoredPla.Add(90);     // Duplicate of 26
63
            //IgnoredPla.Add(36);     // Duplicate of 8
64
            //IgnoredPla.Add(71);     // Duplicate of 25
65
            //IgnoredPla.Add(63);     // Duplicate of 17
66
            //IgnoredPla.Add(87);     // Duplicate of 83
67
            //IgnoredPla.Add(60);     // Duplicate of 15
68
            //IgnoredPla.Add(94);     // Duplicate of 12 and 18
69
            //IgnoredPla.Add(18);     // Duplicate of 12 and 94
70
            //IgnoredPla.Add(93);     // Duplicate of 11 and 19
71
            //IgnoredPla.Add(19);     // Duplicate of 11 and 93
72
            //IgnoredPla.Add(98);     // Duplicate of 37
73
            //IgnoredPla.Add(41);     // Duplicate of 3
74
            //IgnoredPla.Add(32);     // Duplicate of 4
75
 
76
            ////============================================================
77
            //// Special signals (not instructions)
78
            //IgnoredPla.Add(91);     // This signal goes along block IN/OUT instructions.
79
            //IgnoredPla.Add(75);     // This signal specifies a decrement operation for PLA 53, 66 and 105. Otherwise, it is an increment.
80
            //IgnoredPla.Add(55);     // This signal specifies (HL) addressing for all CB-table instructions, PLA entries 70, 72, 73, 74.
81
            //IgnoredPla.Add(44);     // This signal specifies a regular CB opcode (ignoring IX/IY).
82
            //IgnoredPla.Add(33);     // This signal specifies whether the register is being loaded or stored to memory for PLA entry 31.
83
            //IgnoredPla.Add(28);     // This signal specifies the OUT operation for PLA 37. Otherwise, it is operation.
84
            //IgnoredPla.Add(27);     // This signal goes along individual IN/OUT instructions in the ED table.
85
            //IgnoredPla.Add(16);     // This signal specifies a PUSH operation for PLA23. Otherwise, it is a POP operation.
86
            //IgnoredPla.Add(14);     // This signal specifies a decrement operation for PLA 9. Otherwise, it is an increment.
87
            //IgnoredPla.Add(13);     // This signal specifies whether the value is being loaded or stored for PLA entries 8, 30 and 38.
88
            //IgnoredPla.Add(4);      // This signal goes along instructions that access I and R register (PLA 57 and 83).
89
            //IgnoredPla.Add(0);      // This signal specifies *not* to repeat block instructions.
90
 
91
            ////============================================================
92
            //// Ignore our own reserved entries
93
            //IgnoredPla.Add(106);
94
            //IgnoredPla.Add(107);
95
 
96
            //============================================================
97
            // Remove op-bits so we the output is more readable
98
            IgnoredPla.Add(99);
99
            IgnoredPla.Add(100);
100
            IgnoredPla.Add(101);
101
            IgnoredPla.Add(102);
102
            IgnoredPla.Add(103);
103
            IgnoredPla.Add(104);
104
 
105
            // Remove ALU operation entries so the output is more readable
106
            IgnoredPla.Add(88);
107
            IgnoredPla.Add(86);
108
            IgnoredPla.Add(85);
109
            IgnoredPla.Add(84);
110
            IgnoredPla.Add(80);
111
            IgnoredPla.Add(79);
112
            IgnoredPla.Add(78);
113
            IgnoredPla.Add(76);
114
 
115
            //============================================================
116
            // Mark all PLA entries we decided to ignore
117
            foreach (var p in pla)
118
            {
119
                if (IgnoredPla.Contains(p.N))
120
                    p.Ignored = true;
121
            }
122
            return true;
123
        }
124
 
125
        /// 
126
        /// Dumps the content of the entire PLA table
127
        /// 
128
        public void Dump()
129
        {
130
            ClassLog.Log("Content of the PLA table:");
131
            foreach (var p in pla.Where(p => !p.IsDuplicate()))
132
                ClassLog.Log(p.Raw);
133
        }
134
 
135
        /// 
136
        /// Find and return all PLA table entries that trigger on a given condition.
137
        /// 
138
        public List TableMatch(ClassPlaEntry.Modifier modifier, byte instr)
139
        {
140
            var t = new bool[pla.Count];
141
 
142
            // First do a simple search to find the list of *all* PLA entries that match
143
            foreach (var p in pla)
144
            {
145
                if (p.Ignored) continue;
146
                String match = p.Match(modifier, instr);
147
                t[p.N] = !string.IsNullOrEmpty(match);
148
            }
149
 
150
            ////============================================================
151
            //// Apply any intra-PLA conditions. These are hard-coded into the
152
            //// timing spreadsheet and we are duplicating them here:
153
 
154
            //// INC/DEC variations with register, (hl) or (ix+d)
155
            //if (t[66] && !(t[53] || t[105])) ; else t[66] = false;
156
 
157
            //// Generic LD r,r' + (hl), IX variations and on top of that NHALT
158
            //if (t[61] && !(t[59] || t[103] || t[58] || t[102] || t[95])) ; else t[61] = false;
159
            //if (t[58] && !t[95]) ; else t[58] = false;
160
            //if (t[102] && !t[95]) ; else t[102] = false;
161
            //if (t[59] && !t[95]) ; else t[59] = false;
162
            //if (t[103] && !t[95]) ; else t[103] = false;
163
 
164
            //// A single LD (hl),n and LD (ix+d),n has precedence over a set of LD r,n
165
            //if (t[17] && !(t[40] || t[50])) ; else t[17] = false;
166
 
167
            //// ALU A,r' and variations on (hl) and (ix+d)
168
            //if (t[65] && !(t[52] || t[104])) ; else t[65] = false;
169
 
170
            //// ALU
171
            //if (t[88] && (t[65] || t[64] || t[52] || t[104])) ; else t[88] = false;
172
            //if (t[86] && (t[65] || t[64] || t[52] || t[104])) ; else t[86] = false;
173
            //if (t[85] && (t[65] || t[64] || t[52] || t[104])) ; else t[85] = false;
174
            //if (t[84] && (t[65] || t[64] || t[52] || t[104])) ; else t[84] = false;
175
            //if (t[80] && (t[65] || t[64] || t[52] || t[104])) ; else t[80] = false;
176
            //if (t[79] && (t[65] || t[64] || t[52] || t[104])) ; else t[79] = false;
177
            //if (t[78] && (t[65] || t[64] || t[52] || t[104])) ; else t[78] = false;
178
            //if (t[76] && (t[65] || t[64] || t[52] || t[104])) ; else t[76] = false;
179
 
180
            //============================================================
181
 
182
            // Finally, collect and return all PLA entries that are left asserted
183
            return (from p in pla
184
                    where t[p.N]
185
                    select p.Match(modifier, instr)).ToList();
186
        }
187
 
188
        /// 
189
        /// Given the PLA ID, return a list of all opcodes that trigger it
190
        /// 
191
        public List MatchPLA(ClassPlaEntry.Modifier modifier, int id)
192
        {
193
            var m = new List();
194
 
195
            // Find the pla with a given index
196
            foreach (ClassPlaEntry p in pla)
197
            {
198
                if (p.N == id)
199
                {
200
                    // For each possible opcode...
201
                    for (int i = 0; i < 256; i++)
202
                    {
203
                        String match = p.Match(modifier, Convert.ToByte(i));
204
                        if (!string.IsNullOrEmpty(match))
205
                            m.Add(string.Format("{0:X02} => {1}", i, match));
206
                    }
207
                    return m;
208
                }
209
            }
210
            ClassLog.Log("Non-existent PLA index");
211
            return m;
212
        }
213
 
214
        /// 
215
        /// Dump opcode table in various ways.
216
        /// Returns a "selected" list of opcode numbers, that is, opcodes which were tagged by
217
        /// the optional input PLA table number given in arg parameter.
218
        /// 
219
        public List Table(ClassPlaEntry.Modifier modifier, int testNum, int arg)
220
        {
221
            ClassLog.Log(new string('-', 242));
222
            List tagged = new List();
223
            for (int y = 0; y < 16; y++)
224
            {
225
                string line = string.Format("{0:X} ", y);
226
                for (int x = 0; x < 16; x++)
227
                {
228
                    char prefix = ' ';
229
                    byte opcode = Convert.ToByte(y * 16 + x);
230
                    List match = TableMatch(modifier, opcode);
231
                    foreach (string oneMatch in match.Where(oneMatch => Convert.ToInt32(oneMatch.Substring(1, oneMatch.LastIndexOf(']') - 1)) == arg))
232
                    {
233
                        tagged.Add(y * 16 + x);
234
                        prefix = '*';
235
                    }
236
                    string entry = "";
237
 
238
                    //===============================================================================
239
                    // Table 0 - Show the number of PLA entries that match each opcode
240
                    //===============================================================================
241
                    if (testNum == 0)
242
                    {
243
                        entry = string.Join(",", match);
244
                        if (match.Count == 0)
245
                            entry = ".";
246
                        if (match.Count > 1)
247
                            entry = "[" + match.Count + "]";
248
                    }
249
 
250
                    //===============================================================================
251
                    // Table 1 - For each opcode, show all PLA entries that trigger
252
                    //===============================================================================
253
                    if (testNum == 1)
254
                    {
255
                        foreach (string oneMatch in match)
256
                        {
257
                            string n = oneMatch.Substring(1, oneMatch.LastIndexOf(']') - 1);
258
                            entry += n + ",";
259
                        }
260
                        entry = entry.TrimEnd(',');
261
                    }
262
 
263
                    // -------------------------------------------
264
                    if (entry.Length > 12)
265
                        entry = entry.Substring(0, 12);
266
                    line += string.Format(" |{0}{1,-12}", prefix, entry);
267
                }
268
                ClassLog.Log(line);
269
            }
270
            return tagged;
271
        }
272
 
273
        /// 
274
        /// Query PLA table string given as a vector of 0's and 1's
275
        /// This vector is coped from a ModelSim simulation run. The function will decode PLA string
276
        /// into a set of PLA entries that are being triggered ("1")
277
        /// 
278
        public void QueryPla(String bits)
279
        {
280
            int max = pla.Count();
281
            if (bits.Count() != max)
282
            {
283
                ClassLog.Log("Invalid PLA length - the bit array should be " + max + " and it is " + bits.Count());
284
                return;
285
            }
286
            for (int i = 0; i < max; i++)
287
                if (bits[max - i - 1] == '1')
288
                    ClassLog.Log(string.Format(@"pla[{0,3}] = 1;   // {1}", pla[i].N, pla[i].Comment));
289
        }
290
 
291
        /// 
292
        /// Generates a Verilog module with the PLA logic
293
        /// 
294
        public void GenVerilogPla()
295
        {
296
            string max = (pla.Count() - 1).ToString();
297
            string module = "";
298
            module += @"//=====================================================================================" + Environment.NewLine;
299
            module += @"// This file is automatically generated by the z80_pla_checker tool. Do not edit!      " + Environment.NewLine;
300
            module += @"//=====================================================================================" + Environment.NewLine;
301
            module += @"module pla_decode (opcode, prefix, pla);" + Environment.NewLine;
302
            module += @"" + Environment.NewLine;
303
            module += @"input wire [6:0] prefix;" + Environment.NewLine;
304
            module += @"input wire [7:0] opcode;" + Environment.NewLine;
305
            module += @"output reg [" + max + ":0] pla;" + Environment.NewLine;
306
            module += @"" + Environment.NewLine;
307
            module += @"always_comb" + Environment.NewLine;
308
            module += @"begin" + Environment.NewLine;
309
 
310
            foreach (var p in pla)
311
            {
312
                if (p.IsDuplicate())
313
                    continue;
314
                String bitstream = p.GetBitstream();
315
                module += string.Format(@"    if ({{prefix[6:0], opcode[7:0]}} ==? 15'b{0})  pla[{1,3}]=1'b1; else pla[{1,3}]=1'b0;   // {2}",
316
                    bitstream, p.N, p.Comment) + Environment.NewLine;
317
            }
318
 
319
            // Dump all PLA entries that are ignored
320
            module += @"" + Environment.NewLine;
321
            module += @"    // Duplicate or ignored entries" + Environment.NewLine;
322
            foreach (var p in pla)
323
            {
324
                if (p.IsDuplicate())
325
                    module += string.Format(@"    pla[{0,3}]=1'b0;   // {1}", p.N, p.Comment) + Environment.NewLine;
326
            }
327
 
328
            module += @"end" + Environment.NewLine;
329
            module += @"" + Environment.NewLine;
330
            module += @"endmodule" + Environment.NewLine;
331
 
332
            ClassLog.Log(module);
333
        }
334
    }
335
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.