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