aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-09-24 22:23:30 -0400
committerRob Austein <sra@hactrn.net>2015-09-24 22:23:30 -0400
commita8730df1d75d06193335c65b9c9e92c3573ff93d (patch)
treed94426484ee0edaeddc773d641fc9408c25b9d37
parent6f5bf9065d49b7829ddd76b502e4034c745cdec2 (diff)
Convert to something a bit more object-oriented, to simplify adding
additional methods for things like .h and .mk files.
-rwxr-xr-xconfig/config.py437
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()