aboutsummaryrefslogblamecommitdiff
path: root/config/config.py
blob: 86c8615e74d69aa431234a49dd0836e2ead272c6 (plain) (tree)



















































































































































































































                                                                                                       
#!/usr/bin/env python
#
# Generate core_selector.v for a set of cores

import argparse
import re
import sys
if sys.version > '3':
    import configparser
else:
    import ConfigParser as configparser

# defaults
config = 'config.cfg'
outfile = 'core_selector.v'
section = ''
cores = []

# added cores for TRNG, muxed through trng.v
trng_cores = ['avalanche_entropy', 'rosc_entropy', 'trng_mixer', 'trng_csprng']

# parse the command line
def cmdParse():
    global config, outfile, section, cores

    parser = argparse.ArgumentParser()
    parser.add_argument('--cores', help='comma-delimited list of cores')
    parser.add_argument('-c', '--config', default=config,
                        help='config file (default "%s")' % config)
    parser.add_argument('-s', '--section', help='config file section')
    parser.add_argument('-o', '--outfile',
                        help='output file (default "%s")' % outfile)
    args = parser.parse_args()

    if args.cores:
        cores = re.split(',\s*', args.cores)
    if args.config:
        config = args.config
    if args.outfile:
        outfile = args.outfile
    if args.section:
        section = args.section

# parse the config file
def configParse(section):
    cfg = configparser.ConfigParser()
    try:
        with open(config, 'r') as f:
            cfg.readfp(f)
    except (IOError, configparser.MissingSectionHeaderError) as e:
        print e
        exit(1);

    try:
        if not section:
            section = cfg.get('default', 'default')
        cores = cfg.get(section, 'cores')
    except (configparser.NoSectionError, configparser.NoOptionError) as e:
        print e
        exit(1);

    return re.split(r',\s*', cores)

# create an entry in the Core Address Table
def createAddr(core, corenum):
    return "   localparam   CORE_ADDR_{:21s} = 9'h{:02x};\n".format(core.upper(), corenum)

# create an instantiation of the core
# This is complicated because TRNG is a mux for 5 cores.
def createInstance(core):
    core_stripped = re.sub('_\d+$', '', core)
    if core_stripped == 'trng':
        s3 = "(addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG)"
        s4 = "   wire [3:0]           trng_prefix = addr_core_num[3:0] - CORE_ADDR_TRNG;\n"
        s5 = "{trng_prefix, addr_core_reg}"
        s6 = ",\n\n      .avalanche_noise(noise),\n      .debug(debug)"
    else:
        s3 = "(addr_core_num == CORE_ADDR_{0})".format(core.upper())
        s4 = ""
        s5 = "addr_core_reg"
        s6 = ""
    
    return "\
   //----------------------------------------------------------------\n\
   // {1}\n\
   //----------------------------------------------------------------\n\
   wire                 enable_{0} = {3};\n\
   wire [31: 0]         read_data_{0};\n\
   wire                 error_{0};\n\
{4}\n\
   {2} {0}_inst\n\
     (\n\
      .clk(sys_clk),\n\
      .reset_n(~sys_rst),\n\
\n\
      .cs(enable_{0} & (sys_eim_rd | sys_eim_wr)),\n\
      .we(sys_eim_wr),\n\
\n\
      .address({5}),\n\
      .write_data(sys_write_data),\n\
      .read_data(read_data_{0}){6}\n\
      );\n\n\n".format(core, core.upper(), core_stripped, s3, s4, s5, s6)

# create an entry in the Output (Read Data) Multiplexer
def createMux(core, core0):
    return "\
       CORE_ADDR_{0}:\n\
         begin\n\
            sys_read_data_mux = read_data_{1};\n\
            sys_error_mux = error_{1};\n\
         end\n".format(core.upper(), core0)

# create the core_selector module
def createModule(cores):
    cores = ['board_regs', 'comm_regs'] + cores

    # if multiple instances of a core, number them
    for a in set([x for x in cores if cores.count(x) > 1]):
      i = 0
      j = 0
      while (1):
        try:
          j = cores.index(a, j)
        except ValueError:
          break
        cores[j] += '_' + str(i)
        i += 1
        j += 1
    
    addrs = ""
    insts = ""
    muxs = ""
    corenum = 0
    for core in cores:
        addrs += createAddr(core, corenum)
        insts += createInstance(core)
        muxs += createMux(core, core)
        corenum += 1
        if core == 'trng':
            for tcore in trng_cores:
                addrs += createAddr(tcore, corenum)
                muxs += createMux(tcore, core)
                corenum += 1

    # write the boilerplate and all per-core bits
    with open(outfile, 'w') as f:
        f.write("\
// NOTE: This file is generated; do not edit by hand.\n\
\n\
module core_selector\n\
  (\n\
   input wire          sys_clk,\n\
   input wire          sys_rst,\n\
\n\
   input wire [16: 0]  sys_eim_addr,\n\
   input wire          sys_eim_wr,\n\
   input wire          sys_eim_rd,\n\
   output wire [31: 0] sys_read_data,\n\
   input wire [31: 0]  sys_write_data,\n\
   output wire         sys_error,\n\
\n\
   input wire          noise,\n\
   output wire [7 : 0] debug\n\
   );\n\
\n\
\n\
   //----------------------------------------------------------------\n\
   // Address Decoder\n\
   //----------------------------------------------------------------\n\
   // upper 9 bits specify core being addressed\n\
   wire [ 8: 0]         addr_core_num   = sys_eim_addr[16: 8];\n\
   // lower 8 bits specify register offset in core\n\
   wire [ 7: 0]         addr_core_reg   = sys_eim_addr[ 7: 0];\n\
\n\n\
   //----------------------------------------------------------------\n\
   // Core Address Table\n\
   //----------------------------------------------------------------\n\
{0}\n\
\n\
{1}\n\
   //----------------------------------------------------------------\n\
   // Output (Read Data) Multiplexer\n\
   //----------------------------------------------------------------\n\
   reg [31: 0]          sys_read_data_mux;\n\
   assign               sys_read_data = sys_read_data_mux;\n\
   reg                  sys_error_mux;\n\
   assign               sys_error = sys_error_mux;\n\
\n\
   always @*\n\
\n\
     case (addr_core_num)\n\
{2}\n\
       default:\n\
         begin\n\
            sys_read_data_mux = {{32{{1'b0}}}};\n\
            sys_error_mux = 1;\n\
         end\n\
     endcase\n\
\n\
\n\
endmodule\n\
\n\
\n\
//======================================================================\n\
// EOF core_selector.v\n\
//======================================================================\n".format(addrs, insts, muxs))

# main
cmdParse()
if not cores:
    cores = configParse(section)
createModule(cores)