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

Subversion Repositories a-z80

[/] [a-z80/] [trunk/] [cpu/] [control/] [gencompile.py] - Diff between revs 8 and 13

Only display areas with differences | Details | Blame | View Log

Rev 8 Rev 13
#!/usr/bin/env python3
#!/usr/bin/env python3
#
#
# This script reads 'exec_matrix.vh' file and compiles it into an alternate format
# This script reads 'exec_matrix.vh' file and compiles it into an alternate format
# that can be used with Xilinx toolchain.
# that can be used with Xilinx toolchain.
#
#
# Xilinx synthesis tool is effectively not capable of processing that file.
# Xilinx synthesis tool is effectively not capable of processing that file.
# Altera Quartus has no problems compiling it.
# Altera Quartus has no problems compiling it.
#
#
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
#  Copyright (C) 2016  Goran Devic
#  Copyright (C) 2016  Goran Devic
#
#
#  This program is free software; you can redistribute it and/or modify it
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the Free
#  under the terms of the GNU General Public License as published by the Free
#  Software Foundation; either version 2 of the License, or (at your option)
#  Software Foundation; either version 2 of the License, or (at your option)
#  any later version.
#  any later version.
#
#
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
#  more details.
#  more details.
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
import os
import os
import io
import io
import copy
import copy
import tokenize
import tokenize
from io import BytesIO
from io import BytesIO
from tokenize import NAME, INDENT, DEDENT, ENCODING
from tokenize import NAME, INDENT, DEDENT, ENCODING
 
 
# Input file to process
# Input file to process
fname = "exec_matrix.vh"
fname = "exec_matrix.vh"
 
 
# Output file to contain compiled version of the input
# Output file to contain compiled version of the input
oname = "exec_matrix_compiled.vh"
oname = "exec_matrix_compiled.vh"
 
 
# Output file to contain a list of temporary wires used by the compiled Verilog file
# Output file to contain a list of temporary wires used by the compiled Verilog file
tname = "temp_wires.vh"
tname = "temp_wires.vh"
 
 
# Define a list of control signals that are 2-bits wide
# Define a list of control signals that are 2-bits wide
ctls_wide = ['ctl_reg_gp_sel', 'ctl_reg_gp_hilo', 'ctl_reg_sys_hilo', 'ctl_pf_sel']
ctls_wide = ['ctl_reg_gp_sel', 'ctl_reg_gp_hilo', 'ctl_reg_sys_hilo', 'ctl_pf_sel']
 
 
# Help recognizing control signal names
# Help recognizing control signal names
def is_ctl(name):
def is_ctl(name):
    return name.startswith('ctl_') or name=='validPLA' or name=='nextM' or name=='setM1' \
    return name.startswith('ctl_') or name=='validPLA' or name=='nextM' or name=='setM1' \
        or name=='fFetch' or name=='fMRead' or name=='fMWrite' or name=='fIORead' or name=='fIOWrite' \
        or name=='fFetch' or name=='fMRead' or name=='fMWrite' or name=='fIORead' or name=='fIOWrite' \
        or name=='ixy_d' or name=='setIXIY' or name=='setCBED' or name=='nonRep' or name=='pc_inc_hold'
        or name=='ixy_d' or name=='setIXIY' or name=='nonRep' or name=='pc_inc_hold'
 
 
def str2tok(s):
def str2tok(s):
    t = io.BytesIO(bytes(s.encode()))
    t = io.BytesIO(bytes(s.encode()))
    return list(tokenize.tokenize(t.readline))[1:-1]
    return list(tokenize.tokenize(t.readline))[1:-1]
 
 
def tok2str(tokens):
def tok2str(tokens):
    line = [ tokens[n][m].string for n in range(len(tokens)) for m in range(len(tokens[n])) ]
    line = [ tokens[n][m].string for n in range(len(tokens)) for m in range(len(tokens[n])) ]
    return ''.join(line)
    return ''.join(line)
 
 
def get_rval(tokens, i):
def get_rval(tokens, i):
    assert (tokens[i+1].string=='=' or tokens[i+1].string=='|=')
    assert (tokens[i+1].string=='=' or tokens[i+1].string=='|=')
    paren = list(str2tok('()'))
    paren = list(str2tok('()'))
    rval = paren[:1]
    rval = paren[:1]
    while (tokens[i+2].string!=';'):
    while (tokens[i+2].string!=';'):
        rval.append(tokens[i+2])
        rval.append(tokens[i+2])
        i += 1
        i += 1
    rval.extend(paren[1:2])
    rval.extend(paren[1:2])
    return [rval]
    return [rval]
 
 
def decomment(s):
def decomment(s):
    i = s.find('//') # Remove trailing comments from a line
    i = s.find('//') # Remove trailing comments from a line
    if i>=0:
    if i>=0:
        return s[:i]
        return s[:i]
    i = s.find('/*') # Remove comments within a line
    i = s.find('/*') # Remove comments within a line
    j = s.find('*/')
    j = s.find('*/')
    if i>=0 and j>=0:
    if i>=0 and j>=0:
        return decomment(s[:i] + s[j+2:])
        return decomment(s[:i] + s[j+2:])
    return s
    return s
 
 
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
# Generate a sequential-or form for all control wires
# Generate a sequential-or form for all control wires
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
def sequential_or(f, t, tokens):
def sequential_or(f, t, tokens):
    incond = False              # Inside an "if" condition state
    incond = False              # Inside an "if" condition state
    cond = []                   # Condition nested lists
    cond = []                   # Condition nested lists
    ccond = []                  # Currently scanned condition list
    ccond = []                  # Currently scanned condition list
    ctls = {}                   # Dictionary of control wires and their equations
    ctls = {}                   # Dictionary of control wires and their equations
    ccwires = []                # List of wires at the current condition list level
    ccwires = []                # List of wires at the current condition list level
    i = 0                       # Current index into the tokens list
    i = 0                       # Current index into the tokens list
    while i < len(tokens):
    while i < len(tokens):
        tok = tokens[i]
        tok = tokens[i]
        (toknum, tokval, _, _, _) = tok
        (toknum, tokval, _, _, _) = tok
        if incond and not (toknum==NAME and tokval=='begin'):
        if incond and not (toknum==NAME and tokval=='begin'):
            if toknum != DEDENT and toknum != INDENT:
            if toknum != DEDENT and toknum != INDENT:
                ccond.append(tok)
                ccond.append(tok)
        if toknum==NAME:
        if toknum==NAME:
            if tokval=='if':
            if tokval=='if':
                incond = True
                incond = True
            if tokval=='begin': # Push a condition list
            if tokval=='begin': # Push a condition list
                incond = False
                incond = False
                cond.append(copy.deepcopy(ccond))
                cond.append(copy.deepcopy(ccond))
                ccond.clear()
                ccond.clear()
                ccwires.clear()
                ccwires.clear()
            if tokval=='end': # Pop a condition list
            if tokval=='end': # Pop a condition list
                cond.pop()
                cond.pop()
            if is_ctl(tokval) and not incond:
            if is_ctl(tokval) and not incond:
                rval = get_rval(tokens, i)
                rval = get_rval(tokens, i)
                linesub = tok2str(cond)
                linesub = tok2str(cond)
                rhs = tok2str(rval)
                rhs = tok2str(rval)
                line = "{0} = {0} | ".format(tokval)
                line = "{0} = {0} | ".format(tokval)
                if tokval in ccwires: # Check for duplicate assignments
                if tokval in ccwires: # Check for duplicate assignments
                    hint = [ cond[n][m].string for n in range(len(cond)) for m in range(len(cond[n])) ]
                    hint = [ cond[n][m].string for n in range(len(cond)) for m in range(len(cond[n])) ]
                    print ("WARNING: {0}: Multiple assignment of {1}".format(''.join(hint), tokval))
                    print ("WARNING: {0}: Multiple assignment of {1}".format(''.join(hint), tokval))
                ccwires.append(tokval) # Track this wire as assigned at this condition level
                ccwires.append(tokval) # Track this wire as assigned at this condition level
                if tokval in ctls_wide:
                if tokval in ctls_wide:
                    tr = linesub.translate(str.maketrans(dict.fromkeys('~','n'))) # Make temporary name
                    tr = linesub.translate(str.maketrans(dict.fromkeys('~','n'))) # Make temporary name
                    tmpname = "{0}_{1}_{2}".format(tokval, tr.translate(str.maketrans(dict.fromkeys('[]()&',None))), len(ccwires))
                    tmpname = "{0}_{1}_{2}".format(tokval, tr.translate(str.maketrans(dict.fromkeys('[]()&',None))), len(ccwires))
                    t.write("reg {0};\n".format(tmpname))
                    t.write("reg {0};\n".format(tmpname))
                    line = "{0} = {1};\n".format(tmpname, linesub) + line
                    line = "{0} = {1};\n".format(tmpname, linesub) + line
                    line += "({{{0},{0}}}){1}".format(tmpname, rhs)
                    line += "({{{0},{0}}}){1}".format(tmpname, rhs)
                else:
                else:
                    line += linesub + rhs
                    line += linesub + rhs
                line = line.replace(')(', ')&(')
                line = line.replace(')(', ')&(')
                line = line.replace('&&', '&')
                line = line.replace('&&', '&')
                line = line.replace('(1)&', '')
                line = line.replace('(1)&', '')
                line = line.replace('&(1)', '')
                line = line.replace('&(1)', '')
                i += len(rval[0])
                i += len(rval[0])
                f.write ('{0};\n'.format(line))
                f.write ('{0};\n'.format(line))
        i += 1
        i += 1
 
 
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
tokens = []
tokens = []
# Input file which we are processing
# Input file which we are processing
with open(fname) as f:
with open(fname) as f:
    lines = f.readlines()
    lines = f.readlines()
 
 
for line in lines:
for line in lines:
    src = decomment(line)
    src = decomment(line)
    src = bytes(src.encode())
    src = bytes(src.encode())
    src = io.BytesIO(src)
    src = io.BytesIO(src)
    toklist = list(tokenize.tokenize(src.readline))
    toklist = list(tokenize.tokenize(src.readline))
    tokens.extend(toklist)
    tokens.extend(toklist)
 
 
with open(oname, 'w') as f:
with open(oname, 'w') as f:
    with open(tname, 'w') as t:
    with open(tname, 'w') as t:
        f.write("// Automatically generated by gencompile.py\n\n")
        f.write("// Automatically generated by gencompile.py\n\n")
        t.write("// Automatically generated by gencompile.py\n\n")
        t.write("// Automatically generated by gencompile.py\n\n")
        sequential_or(f, t, tokens)
        sequential_or(f, t, tokens)
 
 
# Touch a file that includes 'exec_matrix_compiled.vh' to ensure it will recompile correctly
# Touch a file that includes 'exec_matrix_compiled.vh' to ensure it will recompile correctly
os.utime("execute.v", None)
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.