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

Subversion Repositories a-z80

[/] [a-z80/] [trunk/] [cpu/] [control/] [gencompile.py] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 gdevic
#!/usr/bin/env python3
2
#
3
# This script reads 'exec_matrix.vh' file and compiles it into an alternate format
4
# that can be used with Xilinx toolchain.
5
#
6
# Xilinx synthesis tool is effectively not capable of processing that file.
7
# Altera Quartus has no problems compiling it.
8
#
9
#-------------------------------------------------------------------------------
10
#  Copyright (C) 2016  Goran Devic
11
#
12
#  This program is free software; you can redistribute it and/or modify it
13
#  under the terms of the GNU General Public License as published by the Free
14
#  Software Foundation; either version 2 of the License, or (at your option)
15
#  any later version.
16
#
17
#  This program is distributed in the hope that it will be useful, but WITHOUT
18
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
20
#  more details.
21
#-------------------------------------------------------------------------------
22
import os
23
import io
24
import copy
25
import tokenize
26
from io import BytesIO
27
from tokenize import NAME, INDENT, DEDENT, ENCODING
28
 
29
# Input file to process
30
fname = "exec_matrix.vh"
31
 
32
# Output file to contain compiled version of the input
33
oname = "exec_matrix_compiled.vh"
34
 
35
# Output file to contain a list of temporary wires used by the compiled Verilog file
36
tname = "temp_wires.vh"
37
 
38
# Define a list of control signals that are 2-bits wide
39
ctls_wide = ['ctl_reg_gp_sel', 'ctl_reg_gp_hilo', 'ctl_reg_sys_hilo', 'ctl_pf_sel']
40
 
41
# Help recognizing control signal names
42
def is_ctl(name):
43
    return name.startswith('ctl_') or name=='validPLA' or name=='nextM' or name=='setM1' \
44
        or name=='fFetch' or name=='fMRead' or name=='fMWrite' or name=='fIORead' or name=='fIOWrite' \
45 13 gdevic
        or name=='ixy_d' or name=='setIXIY' or name=='nonRep' or name=='pc_inc_hold'
46 8 gdevic
 
47
def str2tok(s):
48
    t = io.BytesIO(bytes(s.encode()))
49
    return list(tokenize.tokenize(t.readline))[1:-1]
50
 
51
def tok2str(tokens):
52
    line = [ tokens[n][m].string for n in range(len(tokens)) for m in range(len(tokens[n])) ]
53
    return ''.join(line)
54
 
55
def get_rval(tokens, i):
56
    assert (tokens[i+1].string=='=' or tokens[i+1].string=='|=')
57
    paren = list(str2tok('()'))
58
    rval = paren[:1]
59
    while (tokens[i+2].string!=';'):
60
        rval.append(tokens[i+2])
61
        i += 1
62
    rval.extend(paren[1:2])
63
    return [rval]
64
 
65
def decomment(s):
66
    i = s.find('//') # Remove trailing comments from a line
67
    if i>=0:
68
        return s[:i]
69
    i = s.find('/*') # Remove comments within a line
70
    j = s.find('*/')
71
    if i>=0 and j>=0:
72
        return decomment(s[:i] + s[j+2:])
73
    return s
74
 
75
#--------------------------------------------------------------------------------
76
# Generate a sequential-or form for all control wires
77
#--------------------------------------------------------------------------------
78
def sequential_or(f, t, tokens):
79
    incond = False              # Inside an "if" condition state
80
    cond = []                   # Condition nested lists
81
    ccond = []                  # Currently scanned condition list
82
    ctls = {}                   # Dictionary of control wires and their equations
83
    ccwires = []                # List of wires at the current condition list level
84
    i = 0                       # Current index into the tokens list
85
    while i < len(tokens):
86
        tok = tokens[i]
87
        (toknum, tokval, _, _, _) = tok
88
        if incond and not (toknum==NAME and tokval=='begin'):
89
            if toknum != DEDENT and toknum != INDENT:
90
                ccond.append(tok)
91
        if toknum==NAME:
92
            if tokval=='if':
93
                incond = True
94
            if tokval=='begin': # Push a condition list
95
                incond = False
96
                cond.append(copy.deepcopy(ccond))
97
                ccond.clear()
98
                ccwires.clear()
99
            if tokval=='end': # Pop a condition list
100
                cond.pop()
101
            if is_ctl(tokval) and not incond:
102
                rval = get_rval(tokens, i)
103
                linesub = tok2str(cond)
104
                rhs = tok2str(rval)
105
                line = "{0} = {0} | ".format(tokval)
106
                if tokval in ccwires: # Check for duplicate assignments
107
                    hint = [ cond[n][m].string for n in range(len(cond)) for m in range(len(cond[n])) ]
108
                    print ("WARNING: {0}: Multiple assignment of {1}".format(''.join(hint), tokval))
109
                ccwires.append(tokval) # Track this wire as assigned at this condition level
110
                if tokval in ctls_wide:
111
                    tr = linesub.translate(str.maketrans(dict.fromkeys('~','n'))) # Make temporary name
112
                    tmpname = "{0}_{1}_{2}".format(tokval, tr.translate(str.maketrans(dict.fromkeys('[]()&',None))), len(ccwires))
113
                    t.write("reg {0};\n".format(tmpname))
114
                    line = "{0} = {1};\n".format(tmpname, linesub) + line
115
                    line += "({{{0},{0}}}){1}".format(tmpname, rhs)
116
                else:
117
                    line += linesub + rhs
118
                line = line.replace(')(', ')&(')
119
                line = line.replace('&&', '&')
120
                line = line.replace('(1)&', '')
121
                line = line.replace('&(1)', '')
122
                i += len(rval[0])
123
                f.write ('{0};\n'.format(line))
124
        i += 1
125
 
126
#--------------------------------------------------------------------------------
127
tokens = []
128
# Input file which we are processing
129
with open(fname) as f:
130
    lines = f.readlines()
131
 
132
for line in lines:
133
    src = decomment(line)
134
    src = bytes(src.encode())
135
    src = io.BytesIO(src)
136
    toklist = list(tokenize.tokenize(src.readline))
137
    tokens.extend(toklist)
138
 
139
with open(oname, 'w') as f:
140
    with open(tname, 'w') as t:
141
        f.write("// Automatically generated by gencompile.py\n\n")
142
        t.write("// Automatically generated by gencompile.py\n\n")
143
        sequential_or(f, t, tokens)
144
 
145
# Touch a file that includes 'exec_matrix_compiled.vh' to ensure it will recompile correctly
146
os.utime("execute.v", None)

powered by: WebSVN 2.1.0

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