diff options
Diffstat (limited to 'config/config.py')
-rwxr-xr-x | config/config.py | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/config/config.py b/config/config.py new file mode 100755 index 0000000..86c8615 --- /dev/null +++ b/config/config.py @@ -0,0 +1,212 @@ +#!/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) |