diff options
author | Rob Austein <sra@hactrn.net> | 2015-09-24 22:23:30 -0400 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2015-09-24 22:23:30 -0400 |
commit | a8730df1d75d06193335c65b9c9e92c3573ff93d (patch) | |
tree | d94426484ee0edaeddc773d641fc9408c25b9d37 | |
parent | 6f5bf9065d49b7829ddd76b502e4034c745cdec2 (diff) |
Convert to something a bit more object-oriented, to simplify adding
additional methods for things like .h and .mk files.
-rwxr-xr-x | config/config.py | 437 |
1 files changed, 239 insertions, 198 deletions
diff --git a/config/config.py b/config/config.py index bdbda1a..29179e4 100755 --- a/config/config.py +++ b/config/config.py @@ -4,209 +4,250 @@ 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 +import ConfigParser +def main(): 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) + parser.add_argument("--cores", help = "comma-delimited list of cores") + parser.add_argument("-c", "--config", default = "config.cfg", help = "config file") + parser.add_argument("-s", "--section", help = "config file section") + parser.add_argument("-o", "--outfile", default = "core_selector.v", help = "output file") 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): + cores = args.cores + + if not cores: try: - j = cores.index(a, j) - except ValueError: - break - cores[j] += '_' + str(i) - i += 1 - j += 1 - - addrs = "" - insts = "" - muxs = "" - corenum = 0 + cfg = ConfigParser.RawConfigParser() + with open(args.config, "r") as f: + cfg.readfp(f) + section = args.section or cfg.get("default", "default") + cores = cfg.get(section, "cores") + except (IOError, ConfigParser.MissingSectionHeaderError,ConfigParser.NoSectionError, configparser.NoOptionError) as e: + exit(str(e)) + + cores = re.split(r",\s*", cores) + + cores = [Core.new(core) for core in ["board_regs", "comm_regs"] + cores] + core_number = 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)) + core_number = core.assign_core_number(core_number) + + with open(args.outfile, "w") as f: + f.write(createModule_template.format( + addrs = "".join(core.createAddr() for core in cores), + insts = "".join(core.createInstance() for core in cores), + muxes = "".join(core.createMux() for core in cores))) + + +class Core(object): + + _instance_count = {} + special_class = {} + + def __init__(self, name): + self.name = name + self.core_number = None + self.instance_number = self._instance_count.get(name, 0) + self._instance_count[name] = self.instance_number + 1 + + @classmethod + def new(cls, name): + return cls.special_class.get(name, cls)(name) + + def assign_core_number(self, n): + self.core_number = n + return n + 1 + + @property + def instance_name(self): + if self._instance_count[self.name] > 1: + return "{}_{}".format(self.name, self.instance_number) + else: + return self.name + + @property + def upper_instance_name(self): + return self.instance_name.upper() + + @property + def createInstance_template(self): + return createInstance_template_generic + + def createInstance(self): + return self.createInstance_template.format(core = self) + + def createAddr(self): + return createAddr_template.format(core = self) + + def createMux(self): + return createMux_template.format(core = self, core0 = self) + + +class SubCore(Core): + + def __init__(self, name, parent): + super(SubCore, self).__init__(name) + self.parent = parent + + def createMux(self): + return createMux_template.format(core = self, core0 = self.parent) + + +class TRNGCore(Core): + + def __init__(self, name): + super(TRNGCore, self).__init__(name) + self.subcores = tuple(SubCore(name, self) for name in ("avalanche_entropy", "rosc_entropy", "trng_mixer", "trng_csprng")) + + def assign_core_number(self, n): + n = super(TRNGCore, self).assign_core_number(n) + for subcore in self.subcores: + n = subcore.assign_core_number(n) + return n + + @property + def createInstance_template(self): + return createInstance_template_TRNG + + def createAddr(self): + return super(TRNGCore, self).createAddr() + "".join(subcore.createAddr() for subcore in self.subcores) + + def createMux(self): + return super(TRNGCore, self).createMux() + "".join(subcore.createMux() for subcore in self.subcores) + +Core.special_class["trng"] = TRNGCore + + +createAddr_template = """\ + localparam CORE_ADDR_{core.upper_instance_name:21s} = 9'h{core.core_number:02x}; +""" + +createInstance_template_generic = """\ + //---------------------------------------------------------------- + // {core.upper_instance_name} + //---------------------------------------------------------------- + wire enable_{core.instance_name} = (addr_core_num == CORE_ADDR_{core.upper_instance_name}); + wire [31: 0] read_data_{core.instance_name}; + wire error_{core.instance_name}; + + {core.name} {core.instance_name}_inst + ( + .clk(sys_clk), + .reset_n(~sys_rst), + + .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)), + .we(sys_eim_wr), + + .address(addr_core_reg), + .write_data(sys_write_data), + .read_data(read_data_{core.instance_name}) + ); + + +""" + +createInstance_template_TRNG = """\ + //---------------------------------------------------------------- + // {core.upper_instance_name} + //---------------------------------------------------------------- + wire enable_{core.instance_name} = (addr_core_num >= CORE_ADDR_TRNG) && (addr_core_num <= CORE_ADDR_TRNG_CSPRNG); + wire [31: 0] read_data_{core.instance_name}; + wire error_{core.instance_name}; + wire [3:0] trng_prefix = addr_core_num[3:0] - CORE_ADDR_TRNG; + + {core.name} {core.instance_name}_inst + ( + .clk(sys_clk), + .reset_n(~sys_rst), + + .cs(enable_{core.instance_name} & (sys_eim_rd | sys_eim_wr)), + .we(sys_eim_wr), + + .address({{trng_prefix, addr_core_reg}}), + .write_data(sys_write_data), + .read_data(read_data_{core.instance_name}), + + .avalanche_noise(noise), + .debug(debug) + ); + + +""" + +createMux_template = """\ + CORE_ADDR_{core.upper_instance_name}: + begin + sys_read_data_mux = read_data_{core0.instance_name}; + sys_error_mux = error_{core0.instance_name}; + end +""" + +createModule_template = """\ +// NOTE: This file is generated; do not edit by hand. + +module core_selector + ( + input wire sys_clk, + input wire sys_rst, + + input wire [16: 0] sys_eim_addr, + input wire sys_eim_wr, + input wire sys_eim_rd, + output wire [31: 0] sys_read_data, + input wire [31: 0] sys_write_data, + output wire sys_error, + + input wire noise, + output wire [7 : 0] debug + ); + + + //---------------------------------------------------------------- + // Address Decoder + //---------------------------------------------------------------- + // upper 9 bits specify core being addressed + wire [ 8: 0] addr_core_num = sys_eim_addr[16: 8]; + // lower 8 bits specify register offset in core + wire [ 7: 0] addr_core_reg = sys_eim_addr[ 7: 0]; + + + //---------------------------------------------------------------- + // Core Address Table + //---------------------------------------------------------------- +{addrs} + +{insts} + //---------------------------------------------------------------- + // Output (Read Data) Multiplexer + //---------------------------------------------------------------- + reg [31: 0] sys_read_data_mux; + assign sys_read_data = sys_read_data_mux; + reg sys_error_mux; + assign sys_error = sys_error_mux; + + always @* + + case (addr_core_num) +{muxes} + default: + begin + sys_read_data_mux = {{32{{1'b0}}}}; + sys_error_mux = 1; + end + endcase + + +endmodule + + +//====================================================================== +// EOF core_selector.v +//====================================================================== +""" # main -cmdParse() -if not cores: - cores = configParse(section) -createModule(cores) + + +if __name__ == "__main__": + main() |