OpenCores
URL https://opencores.org/ocsvn/light52/light52/trunk

Subversion Repositories light52

[/] [light52/] [trunk/] [tools/] [build_opcode_table/] [svg_op_table.py] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 ja_rd
#!/usr/bin/env python
2
"""
3
svg_op_table.py: Build 3 SVG files with the MCS51 opcode table decorated with
4
cycle count information extracted from the cycle count simulation log file.
5
"""
6
__author__ = "Jose A. Ruiz"
7
__license__ = "LGPL"
8
 
9
 
10
import sys
11
import getopt
12
 
13
 
14
def read_cycle_info(filename):
15
    """
16
    the file should have 256 lines of text.
17
    Each line has 4 comma-separated fields:
18
        opcode, minimum cycle count, maximum cycle count, number of executions.
19
    The number of executions is the number of times the opcode was executed by
20
    the simulation that produced the log.
21
    If this number is zero, or if the minimum cycle count is >= 999, then
22
    the opcode has not been executed and there's no cycle count data for it.
23
 
24
    This function returns a list of 256 tuples sorted by opcode, with the
25
    above 3 values (the opcode is excluded).
26
    """
27
 
28
    # Open file and read it into a list of lines.
29
    fin = open(filename, "r")
30
    lines = fin.readlines()
31
    fin.close()
32
 
33
    info = [[]] * 256;
34
 
35
    for line in lines:
36
        fields = line.split(',')
37
        opc = int(fields[0],16)
38
        info[opc] = (int(fields[1]), int(fields[2]), int(fields[3]))
39
    return info
40
 
41
 
42
def read_opcode_info(filename):
43
    """
44
    Read a table of MCS51 opcodes from a plain text file.
45
    Rather than writing here a lengthy explanation I invite you to see the
46
    opcode table text file "opcode_info.txt".
47
    Since the file is known, we don't provide for formatting errors, missing
48
    lines or any kind of trouble.
49
    This file has been copy-pasted straight from Keil's website and slightly
50
    edited.
51
    """
52
 
53
    # Open file and read it into a list of lines.
54
    fin = open(filename, "r")
55
    lines = fin.readlines()
56
    fin.close()
57
 
58
    # We'll build a table with 256 entries, one per opcode.
59
    info = [[]] * 256;
60
 
61
    for line in lines:
62
        [opcode, _, line] = line.partition('\t')
63
        [nbytes, _, line] = line.partition('\t')
64
        [mnemonic, _, operands] = line.partition('\t')
65
        i = int(opcode, 16)
66
        info[i] = [mnemonic.strip(), operands.strip(), int(nbytes)]
67
 
68
    return info
69
 
70
def opcode_unimplemented(opc):
71
    """Return true if the opcode is not implemented (implemented as NOP)."""
72
    # FIXME this should be optional, like the implementation itself.
73
    return opc=="DA" or opc=="XCHD"
74
 
75
 
76
def build_svg_table(info, cycles, part):
77
    """
78
    Render the opcode table, or one half of it, in SVG format.
79
    @arg info Array of opcode information as returned by read_opcode_info.
80
    @arg cycles Array of opcode cycle counts as returned by read_cycle_info.
81
    @arg part Can be one of ("left","right","full").
82
    Return a string in SVG format to be written to a file.
83
    """
84
 
85
 
86
    # (lc,hc) is the range of columns we're going to draw. It can be the whole 
87
    # table or the left or right half.
88
    if part=="left":
89
        lc = 0
90
        hc = 8
91
    elif part=="right":
92
        lc = 8
93
        hc = 16
94
    else:
95
        lc = 0
96
        hc = 16
97
 
98
    # Hardcode the rendering parameters: size of the cells, etc.
99
    # Note that other parameters (font size and text coordinates) are hardcoded
100
    # in the string literals below.
101
    scale = 1.0
102
    c_width = 300
103
    c_height = 200
104
    cr_height = c_height
105
    cr_width = c_width / 2
106
    cc_height = c_height / 2
107
    cc_width = c_width
108
 
109
    # Compute the SVG frame size according to the selected part.
110
    w = hc - lc
111
    width = c_width*w + cr_width + 20
112
    height = c_height*16 + cc_height + 20
113
 
114
    # This is the SVG header template. 
115
    header = \
116
    "<svg xmlns='http://www.w3.org/2000/svg' \n" + \
117
    "xmlns:xlink='http://www.w3.org/1999/xlink' \n" + \
118
    "width='%d' height='%d' viewbox='0 0 %d %d' \n" + \
119
    "preserveAspectRatio='none'>\n\n"
120
 
121
    # We'll append all the SVG text onto this variable.
122
    svg = ""
123
 
124
    # Build the SVG header with the selected size.
125
    svg = svg + header % (width, height, width, height)
126
 
127
    # SVG definitions template. There's 3 cells, for the table borders and
128
    # the table body.
129
    defs = \
130
    '<defs>\n' + \
131
    '<!-- Basic table cell -->\n' + \
132
    '<rect height="%d" width="%d" stroke="black" stroke-width="1" id="s"/>\n' + \
133
    '<!-- Row index cell -->\n' + \
134
    '<rect height="%d" width="%d" stroke="black" stroke-width="1" id="r"/>\n' + \
135
    '<!-- Col index cell -->\n' + \
136
    '<rect height="%d" width="%d" stroke="black" stroke-width="1" id="c"/>\n' + \
137
    '</defs>\n\n'
138
 
139
    # Build SVG definitions block with its parameters -- cell sizes.
140
    svg = svg + defs % (c_height, c_width, cr_height, cr_width, cc_height, cc_width)
141
 
142
    # This is a SVG group template for the main table cell.
143
    # Note that the font sizes and text coordinates are hardcoded!
144
    base_cell = \
145
    '<g transform="translate(%d,%d) scale(%f)">\n' + \
146
    '<use x="0" y="0" xlink:href="#s" fill="%s"/>\n' + \
147
    '<text x="80" y="90" font-family="sans-serif" font-size="55">%s</text>\n' + \
148
    '<text x="80" y="140" font-family="sans-serif" font-size="40">%s</text>\n' + \
149
    '<text x="10" y="40" font-family="verdana" fill="red" font-size="40">%s</text>\n' + \
150
    '<text x="260" y="40" font-family="verdana" fill="blue" font-size="40">%d</text>\n' + \
151
    '</g>\n\n'
152
 
153
    # SCG group template for a cell to the left of the table with a row number.
154
    row_index_cell = \
155
    '<g transform="translate(%d,%d) scale(%f)">\n' + \
156
    '<use x="0" y="0" xlink:href="#r" fill="white"/>\n' + \
157
    '<text x="80" y="90" font-family="sans-serif" font-size="55">%01X</text>\n' + \
158
    '</g>\n\n'
159
 
160
    # SCG group template for a cell at the top of the table with a col number.
161
    col_index_cell = \
162
    '<g transform="translate(%d,%d) scale(%f)">\n' + \
163
    '<use x="0" y="0" xlink:href="#c" fill="white"/>\n' + \
164
    '<text x="80" y="70" font-family="sans-serif" font-size="55">%01X</text>\n' + \
165
    '</g>\n\n'
166
 
167
    # Build the top row of the table: cells with the column number.
168
    for col in range(lc,hc):
169
        y = 10
170
        x = 10 + (cr_width + (col-lc)*c_width)*scale
171
        svg = svg + col_index_cell % (x, 10, scale, col)
172
 
173
    # Now, for each of the 16 rows...
174
    for row in range(16):
175
        # ...compute the row vertical coordinate...
176
        y = 10 + (cc_height + row*c_height)*scale
177
        # ...render the leftmost cell with the row index...
178
        svg = svg + row_index_cell % (10, y, scale, row)
179
        # ...and render the row of main-table-body cells.
180
 
181
        # for each of the cells in the column range we're rendering...
182
        for col in range(lc,hc):
183
            # ...compute the horizintal coordinate of the cell...
184
            x = 10 + (cr_width + (col-lc)*c_width)*scale
185
 
186
            # ...and extract the cycle count data from the array.
187
            opc = col*16 + row
188
            min = cycles[opc][0]
189
            max = cycles[opc][1]
190
            # When min/=max we need to display both values (conditional
191
            # jumps, for instance).
192
            # Those opcodes with a min value >=999 have not been executed by 
193
            # the simulation and we'll render them in a darker shade of grey.
194
            if min < 999:
195
                if min==max:
196
                    count = str(min)
197
                else:
198
                    count = str(min) + "/" + str(max)
199
                color = "white"
200
            else:
201
                count = " "
202
                color = "#e0e0e0"
203
 
204
            # Render the cell with all its parameters.
205
 
206
 
207
            # Render the 'optional' opcodes in red.
208
            if opcode_unimplemented(info[opc][0]):
209
                color = "#f0b0b0"
210
 
211
            cell = base_cell % (x, y, scale, color, info[opc][0], info[opc][1], count, info[opc][2])
212
 
213
            svg = svg + cell
214
 
215
    # Done, close the SVG element and we're done.
216
    svg = svg + '</svg>'
217
 
218
    return svg
219
 
220
 
221
def write_cycle_table(cycle_info, c_table_file):
222
    """
223
    Writes the cycle count info in the format of a C literal table.
224
    Meant to be copied and pasted into the B51 simulator.
225
    """
226
 
227
    txt = "typedef struct {\n"
228
    txt = txt + "    int min;\n"
229
    txt = txt + "    int max;\n"
230
    txt = txt + "} cycle_count_t;\n"
231
    txt = txt + "\n\n"
232
    txt = txt + "cycle_count_t cycle_count[256] = {\n    "
233
    for i in range(len(cycle_info)):
234
        item = cycle_info[i]
235
        if item[2] == 0:
236
            txt = txt + "{ 0, 0}, "
237
        else:
238
            txt = txt + "{%2u,%2u}, " % (item[0], item[1])
239
        if (i % 8) == 7:
240
            txt = txt + "\n    "
241
    txt = txt + "};\n\n"
242
 
243
 
244
    fout = open(c_table_file, "w")
245
    fout.write(txt)
246
    fout.close()
247
 
248
 
249
def main(argv):
250
    """Main body of the program."""
251
 
252
    # We should parse the command line arguments, etc. 
253
    # For this quick-and-dirty script we'll hardcode all the parameters...
254
 
255
    # ...the target svg file names...
256
    svg_base_filename = "./table"
257
    # ...the target text file name where a C-format table with the cycle counts
258
    # will be written to...
259
    c_table_file = "./cycle_table.c"
260
    # ...and the source CSV cycle count log file. Note this path is the default
261
    # working path for the Modelsim simulations, change if necessary.
262
    cycle_log_filename = "../../sim/cycle_count_log.csv"
263
 
264
    # Read cycle count data...
265
    cycle_info = read_cycle_info(cycle_log_filename)
266
    # ...and read opcode table data (instruction mnemonics and byte counts).
267
    opcode_info = read_opcode_info("opcode_info.txt")
268
 
269
    # First of all, write the C-format cycle table, to be copied and pasted
270
    # into the B51 simulator.
271
    write_cycle_table(cycle_info, c_table_file)
272
 
273
    # We can render the opcode table 'whole', resulting in a wide table, or
274
    # we can render the left and right halves separately, which gives a format
275
    # better suted for a printed page. 
276
 
277
    # So, for all three possible rendering formats...
278
    parts = ("left", "right", "full")
279
    # ...render the opcode table.
280
    for part in parts:
281
 
282
        # Build the SVG text for the table...
283
        svg = build_svg_table(opcode_info, cycle_info, part)
284
        # ...and write it to the target file.
285
        fout = None
286
        try:
287
            full_filename = svg_base_filename + "_" + part + ".svg"
288
            fout = open(full_filename, "w")
289
            fout.write(svg)
290
            fout.close()
291
            print "SVG opcode table written to %s" % full_filename
292
        except:
293
            print "Trouble opening %s for output" % full_filename
294
        finally:
295
            if fout: fout.close()
296
 
297
 
298
if __name__ == "__main__":
299
    main(sys.argv[1:])
300
    sys.exit(0)
301
 
302
 

powered by: WebSVN 2.1.0

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