#!/usr/bin/env python # # Generate core_selector.v for a set of cores import argparse import re import ConfigParser def main(): parser = argparse.ArgumentParser() 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() cores = args.cores if not cores: try: 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: 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 if __name__ == "__main__": main()