aboutsummaryrefslogblamecommitdiff
path: root/config/config.py
blob: 29179e42f83476bcc47c94ff2678668f574140ef (plain) (tree)
1
2
3
4
5
6
7
8
9





                                             
                   
 
           
                                      



                                                                                             

                              


                      
            











                                                                                                                              
                      





















































































































































































































                                                                                                                                    

      



                          
#!/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()