def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name) self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() config = configparser.SafeConfigParser() config.read(config_file) for section in config.sections(): type = section.split()[0] try: name = section.split()[1] except IndexError: print( "Malformed section header. Format is master|slave <name>") exit(1) if type == "master": print("Found master " + name) self.masters[name] = Master(name, dict(config.items(section))) d[name] = config.get(section, 'slaves').split() elif type == "slave": print("Found slave " + name) self.slaves[name] = Slave(name, dict(config.items(section))) else: print("Invalid section type " + type) exit(1) #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]]
def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name) self.name = name d = OrderedDict() self.slaves = [] self.masters = [] import yaml def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): class OrderedLoader(Loader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return object_pairs_hook(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) return yaml.load(stream, OrderedLoader) data = ordered_load(open(config_file)) config = data['parameters'] self.vlnv = data['vlnv'] for k,v in config['masters'].items(): print("Found master " + k) self.masters.append(Master(k,v)) for k,v in config['slaves'].items(): print("Found slave " + k) self.slaves.append(Slave(k,v)) self.output_file = config.get('output_file', 'axi_intercon.v') self.atop = config.get('atop', False)
def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name); self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() config = configparser.SafeConfigParser() config.read(config_file) for section in config.sections(): type=section.split()[0] try: name=section.split()[1] except IndexError: print("Malformed section header. Format is master|slave <name>") exit(1) if type == "master": print("Found master " + name) self.masters[name] = Master(name, dict(config.items(section))) d[name] = config.get(section, 'slaves').split() elif type == "slave": print("Found slave " + name) self.slaves[name] = Slave(name, dict(config.items(section))) else: print("Invalid section type " + type) exit(1) #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]]
def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name); self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() import yaml def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): class OrderedLoader(Loader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return object_pairs_hook(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) return yaml.load(stream, OrderedLoader) data = ordered_load(open(config_file)) config = data['parameters'] files_root = data['files_root'] self.vlnv = data['vlnv'] valid_endians = ['big', 'little'] if 'endian' in config: self.endian = config['endian'] if self.endian not in valid_endians: raise UnknownPropertyError("Unknown data resizer endian '{}' specified. Valid endians: {}".format(config['endian'], valid_endians)) else: self.endian = "big" print("Wishbone Data Resizer Endian: {}".format(config['endian'])) for k,v in config['masters'].items(): print("Found master " + k) self.masters[k] = Master(k,v) d[k] = v['slaves'] for k,v in config['slaves'].items(): print("Found slave " + k) self.slaves[k] = Slave(k,v) #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]] self.output_file = config.get('output_file', 'wb_intercon.v')
def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name) self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() import yaml def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): class OrderedLoader(Loader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return object_pairs_hook(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) return yaml.load(stream, OrderedLoader) data = ordered_load(open(config_file)) config = data['parameters'] files_root = data['files_root'] self.vlnv = data['vlnv'] index = 0 for k, v in config['masters'].items(): print("Found master " + k) self.masters[k] = Master(k, index, v) index = index + 1 index = 0 for k, v in config['slaves'].items(): print("Found slave " + k) self.slaves[k] = Slave(k, index, v) index = index + 1 #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]] self.output_file = config.get('output_file', 'ahb3lite_intercon.sv')
class AxiIntercon: def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name) self.name = name d = OrderedDict() self.slaves = [] self.masters = [] import yaml def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): class OrderedLoader(Loader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return object_pairs_hook(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) return yaml.load(stream, OrderedLoader) data = ordered_load(open(config_file)) config = data['parameters'] self.vlnv = data['vlnv'] for k,v in config['masters'].items(): print("Found master " + k) self.masters.append(Master(k,v)) for k,v in config['slaves'].items(): print("Found slave " + k) self.slaves.append(Slave(k,v)) self.output_file = config.get('output_file', 'axi_intercon.v') self.atop = config.get('atop', False) def _dump(self): print("*Masters*") for master in self.masters.values(): print(master.name) for slave in master.slaves: print(' ' + slave.name) print("*Slaves*") for slave in self.slaves.values(): print(slave.name) for master in slave.masters: print(' ' + master.name) def write(self): w = Widths() w.addr = 32 w.data = 64 w.user = 0 w.atop = self.atop max_idw = max([m.idw for m in self.masters]) max_sidw = max_idw + int(math.ceil(math.log2(len(self.masters)))) file = self.output_file _template_ports = [Port('clk_i' , 'clk'), Port('rst_ni', 'rst_n')] template_parameters = [] #Module header self.verilog_writer.add(ModulePort('clk_i' , 'input')) self.verilog_writer.add(ModulePort('rst_ni', 'input')) for master in self.masters: for port in module_ports(w, master, master.idw, True): self.verilog_writer.add(port) for wire in template_wires(w, master, master.idw): self.template_writer.add(wire) _template_ports += template_ports(w, master, master.idw, True) for slave in self.slaves: for port in module_ports(w, slave, max_sidw, False): self.verilog_writer.add(port) for wire in template_wires(w, slave, max_sidw): self.template_writer.add(wire) _template_ports += template_ports(w, slave, max_sidw, False) raw = "" nm = len(self.masters) ns = len(self.slaves) raw += """ localparam int unsigned NoMasters = 32'd{}; // How many Axi Masters there are localparam int unsigned NoSlaves = 32'd{}; // How many Axi Slaves there are // axi configuration localparam int unsigned AxiIdWidthMasters = 32'd{}; localparam int unsigned AxiIdUsed = 32'd{}; // Has to be <= AxiIdWidthMasters localparam int unsigned AxiIdWidthSlaves = AxiIdWidthMasters + $clog2(NoMasters); localparam int unsigned AxiAddrWidth = 32'd32; // Axi Address Width localparam int unsigned AxiDataWidth = 32'd64; // Axi Data Width localparam int unsigned AxiStrbWidth = AxiDataWidth / 8; localparam int unsigned AxiUserWidth = 1; """.format(nm, ns, max_idw, max_idw) raw += " localparam axi_pkg::xbar_cfg_t xbar_cfg = '{\n" raw += """ NoSlvPorts: NoMasters, NoMstPorts: NoSlaves, MaxMstTrans: 10, MaxSlvTrans: 6, FallThrough: 1'b0, LatencyMode: axi_pkg::CUT_ALL_AX, AxiIdWidthSlvPorts: AxiIdWidthMasters, AxiIdUsedSlvPorts: AxiIdUsed, UniqueIds: 1'b0, AxiAddrWidth: AxiAddrWidth, AxiDataWidth: AxiDataWidth, NoAddrRules: NoSlaves """ raw += " };\n" raw += """ typedef logic [AxiIdWidthMasters-1:0] id_mst_t; typedef logic [AxiIdWidthSlaves-1:0] id_slv_t; typedef logic [AxiAddrWidth-1:0] addr_t; typedef axi_pkg::xbar_rule_32_t rule_t; // Has to be the same width as axi addr typedef logic [AxiDataWidth-1:0] data_t; typedef logic [AxiStrbWidth-1:0] strb_t; typedef logic [AxiUserWidth-1:0] user_t; `AXI_TYPEDEF_AW_CHAN_T(aw_chan_mst_t, addr_t, id_mst_t, user_t) `AXI_TYPEDEF_AW_CHAN_T(aw_chan_slv_t, addr_t, id_slv_t, user_t) `AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t) `AXI_TYPEDEF_B_CHAN_T(b_chan_mst_t, id_mst_t, user_t) `AXI_TYPEDEF_B_CHAN_T(b_chan_slv_t, id_slv_t, user_t) `AXI_TYPEDEF_AR_CHAN_T(ar_chan_mst_t, addr_t, id_mst_t, user_t) `AXI_TYPEDEF_AR_CHAN_T(ar_chan_slv_t, addr_t, id_slv_t, user_t) `AXI_TYPEDEF_R_CHAN_T(r_chan_mst_t, data_t, id_mst_t, user_t) `AXI_TYPEDEF_R_CHAN_T(r_chan_slv_t, data_t, id_slv_t, user_t) `AXI_TYPEDEF_REQ_T(slv_req_t, aw_chan_mst_t, w_chan_t, ar_chan_mst_t) `AXI_TYPEDEF_RESP_T(slv_resp_t, b_chan_mst_t, r_chan_mst_t) `AXI_TYPEDEF_REQ_T(mst_req_t, aw_chan_slv_t, w_chan_t, ar_chan_slv_t) `AXI_TYPEDEF_RESP_T(mst_resp_t, b_chan_slv_t, r_chan_slv_t) """ raw += " localparam rule_t [{}:0] AddrMap = '".format(ns-1) raw += "{\n" i = 0 rules = [] for slave in self.slaves: rule = " '{" rule += "idx: 32'd{}, start_addr: 32'h{:08x}, end_addr: 32'h{:08x}".format(i, slave.offset, slave.offset+slave.size) rule += "}" i += 1 rules.append(rule) raw += ',\n'.join(rules) raw += "};\n" raw += " slv_req_t [{}:0] masters_req;\n".format(nm-1) raw += " slv_resp_t [{}:0] masters_resp;\n".format(nm-1) raw += " mst_req_t [{}:0] slaves_req;\n".format(ns-1) raw += " mst_resp_t [{}:0] slaves_resp;\n".format(ns-1) ns = len(self.slaves) raw += assigns(w, max_idw, self.masters, self.slaves) self.verilog_writer.raw = raw parameters = [ Parameter('Cfg' , 'xbar_cfg' ), Parameter('ATOPs' , "1'b"+str(int(self.atop))), Parameter('slv_aw_chan_t', 'aw_chan_mst_t'), Parameter('mst_aw_chan_t', 'aw_chan_slv_t'), Parameter('w_chan_t' , 'w_chan_t' ), Parameter('slv_b_chan_t' , 'b_chan_mst_t' ), Parameter('mst_b_chan_t' , 'b_chan_slv_t' ), Parameter('slv_ar_chan_t', 'ar_chan_mst_t'), Parameter('mst_ar_chan_t', 'ar_chan_slv_t'), Parameter('slv_r_chan_t' , 'r_chan_mst_t' ), Parameter('mst_r_chan_t' , 'r_chan_slv_t' ), Parameter('slv_req_t' , 'slv_req_t' ), Parameter('slv_resp_t' , 'slv_resp_t' ), Parameter('mst_req_t' , 'mst_req_t' ), Parameter('mst_resp_t' , 'mst_resp_t' ), Parameter('rule_t' , 'rule_t' ), ] ports = instance_ports(w, max_idw, self.masters, self.slaves) self.verilog_writer.add(Instance('axi_xbar', 'axi_xbar', parameters, ports)) self.template_writer.add(Instance(self.name, self.name, template_parameters, _template_ports)) self.verilog_writer.write(file) self.template_writer.write(file+'h') core_file = self.vlnv.split(':')[2]+'.core' vlnv = self.vlnv with open(core_file, 'w') as f: f.write('CAPI=2:\n') files = [{file : {'file_type' : 'systemVerilogSource'}}, {file+'h' : {'is_include_file' : True, 'file_type' : 'verilogSource'}} ] coredata = {'name' : vlnv, 'targets' : {'default' : {}}, } coredata['filesets'] = {'rtl' : {'files' : files}} coredata['targets']['default']['filesets'] = ['rtl'] f.write(yaml.dump(coredata))
def gen_corescorecore(self, count): corescorecore = VerilogWriter('corescorecore') corescorecore.add(ModulePort('i_clk', 'input')) corescorecore.add(ModulePort('i_rst', 'input')) corescorecore.add(ModulePort('o_tdata', 'output', 8)) corescorecore.add(ModulePort('o_tlast', 'output')) corescorecore.add(ModulePort('o_tvalid', 'output')) corescorecore.add(ModulePort('i_tready', 'input')) corescorecore.add(Wire('tdata', count * 8)) corescorecore.add(Wire('tlast', count)) corescorecore.add(Wire('tvalid', count)) corescorecore.add(Wire('tready', count)) for idx in range(count): base_ports = [ Port('i_clk', 'i_clk'), Port('i_rst', 'i_rst'), Port('o_tdata', 'tdata[{}:{}]'.format(idx * 8 + 7, idx * 8)), Port('o_tlast', 'tlast[{}]'.format(idx)), Port('o_tvalid', 'tvalid[{}]'.format(idx)), Port('i_tready', 'tready[{}]'.format(idx)), ] corescorecore.add( Instance('base', 'core_' + str(idx), [ Parameter('memfile', '"core_{}.hex"'.format(idx)), Parameter('memsize', '256') ], base_ports)) arbports = [ Port('clk', 'i_clk'), Port('rst', 'i_rst'), Port("s_axis_tdata".format(idx), "tdata"), Port("s_axis_tkeep".format(idx), "{}'d0".format(count)), Port("s_axis_tvalid".format(idx), 'tvalid'), Port("s_axis_tready".format(idx), 'tready'), Port("s_axis_tlast".format(idx), 'tlast'), Port("s_axis_tid".format(idx), "{}'d0".format(count * 8)), Port("s_axis_tdest".format(idx), "{}'d0".format(count * 8)), Port("s_axis_tuser".format(idx), "{}'d0".format(count)), Port('m_axis_tdata ', 'o_tdata'), Port('m_axis_tkeep ', ''), Port('m_axis_tvalid', 'o_tvalid'), Port('m_axis_tready', 'i_tready'), Port('m_axis_tlast ', 'o_tlast'), Port('m_axis_tid ', ''), Port('m_axis_tdest ', ''), Port('m_axis_tuser ', ''), ] arbparams = [ Parameter('S_COUNT', count), Parameter('DATA_WIDTH', 8), Parameter('KEEP_ENABLE', 0), Parameter('KEEP_WIDTH', 1), Parameter('ID_ENABLE', 0), Parameter('ID_WIDTH', 8), Parameter('DEST_ENABLE', 0), Parameter('DEST_WIDTH', 8), Parameter('USER_ENABLE', 0), Parameter('USER_WIDTH', 1), Parameter('ARB_TYPE', '"ROUND_ROBIN"'), Parameter('LSB_PRIORITY', '"HIGH"'), ] corescorecore.add( Instance('axis_arb_mux', 'axis_mux', arbparams, arbports)) corescorecore.write('corescorecore.v')
class AHB3Intercon: def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name) self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() import yaml def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): class OrderedLoader(Loader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return object_pairs_hook(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) return yaml.load(stream, OrderedLoader) data = ordered_load(open(config_file)) config = data['parameters'] files_root = data['files_root'] self.vlnv = data['vlnv'] index = 0 for k, v in config['masters'].items(): print("Found master " + k) self.masters[k] = Master(k, index, v) index = index + 1 index = 0 for k, v in config['slaves'].items(): print("Found slave " + k) self.slaves[k] = Slave(k, index, v) index = index + 1 #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]] self.output_file = config.get('output_file', 'ahb3lite_intercon.sv') def _dump(self): print("*Masters*") for master in self.masters.values(): print(master.name) for slave in master.slaves: print(' ' + slave.name) print("*Slaves*") for slave in self.slaves.values(): print(slave.name) for master in slave.masters: print(' ' + master.name) def write(self): file = self.output_file # Template port/parameters template_ports = [Port('clk', 'CLK'), Port('reset_n', 'RESETn')] template_parameters = [] # Gen top level ports self.verilog_writer.add(ModulePort('clk', 'input')) self.verilog_writer.add(ModulePort('reset_n', 'input')) # Declare global wires to pass to instantiation self.verilog_writer.add(LocalParam('MASTERS', len(self.masters))) self.verilog_writer.add(LocalParam('SLAVES', len(self.slaves))) mclog2 = max([math.ceil(math.log2(len(self.masters))), 1]) self.verilog_writer.add(LocalParam('MASTER_BITS', mclog2)) self.verilog_writer.add( Wire('mst_priority', mclog2, append=' [MASTERS]')) self.verilog_writer.add(Wire('slv_addr_base', 32, append=' [SLAVES]')) self.verilog_writer.add(Wire('slv_addr_mask', 32, append=' [SLAVES]')) for p in AHB3_MASTER_PORTS: self.verilog_writer.add( Wire('mst_{0}'.format(p.name), p.width, append=' [MASTERS]')) self.verilog_writer.add( Wire('slv_{0}'.format(p.name), p.width, append=' [SLAVES]')) for p in AHB3_SLAVE_PORTS: self.verilog_writer.add( Wire('mst_{0}'.format(p.name), p.width, append=' [MASTERS]')) self.verilog_writer.add( Wire('slv_{0}'.format(p.name), p.width, append=' [SLAVES]')) # Add HREADY/HREADYOUT self.verilog_writer.add(Wire('mst_HREADY', append=' [MASTERS]')) self.verilog_writer.add(Wire('slv_HREADY', append=' [SLAVES]')) self.verilog_writer.add(Wire('mst_HREADYOUT', append=' [MASTERS]')) self.verilog_writer.add(Wire('slv_HREADYOUT', append=' [SLAVES]')) # Generate master wires for key, value in self.masters.items(): for p in AHB3_MASTER_PORTS: self.template_writer.add( Wire('{0}_{1}'.format(key, p.name), p.width)) self.verilog_writer.add( ModulePort('{0}_{1}'.format(key, p.name), 'input', p.width)) template_ports += [ Port('{0}_{1}'.format(key, p.name), '{0}_{1}'.format(key, p.name)) ] for p in AHB3_SLAVE_PORTS: self.template_writer.add( Wire('{0}_{1}'.format(key, p.name), p.width)) self.verilog_writer.add( ModulePort('{0}_{1}'.format(key, p.name), 'output', p.width)) template_ports += [ Port('{0}_{1}'.format(key, p.name), '{0}_{1}'.format(key, p.name)) ] # Add HREADY input port self.verilog_writer.add( ModulePort('{0}_{1}'.format(key, 'HREADY'), 'output')) self.template_writer.add(Wire('{0}_{1}'.format(key, 'HREADY'))) template_ports += [ Port('{0}_{1}'.format(key, 'HREADY'), '{0}_{1}'.format(key, 'HREADY')) ] # Generate slave wires for key, value in self.slaves.items(): for p in AHB3_MASTER_PORTS: self.template_writer.add( Wire('{0}_{1}'.format(key, p.name), p.width)) self.verilog_writer.add( ModulePort('{0}_{1}'.format(key, p.name), 'output', p.width)) template_ports += [ Port('{0}_{1}'.format(key, p.name), '{0}_{1}'.format(key, p.name)) ] for p in AHB3_SLAVE_PORTS: self.template_writer.add( Wire('{0}_{1}'.format(key, p.name), p.width)) self.verilog_writer.add( ModulePort('{0}_{1}'.format(key, p.name), 'input', p.width)) template_ports += [ Port('{0}_{1}'.format(key, p.name), '{0}_{1}'.format(key, p.name)) ] # Add HREADY/HREADYOUT ports self.template_writer.add(Wire('{0}_{1}'.format(key, 'HREADY'))) self.verilog_writer.add( ModulePort('{0}_{1}'.format(key, 'HREADY'), 'output')) self.template_writer.add(Wire('{0}_{1}'.format(key, 'HREADYOUT'))) self.verilog_writer.add( ModulePort('{0}_{1}'.format(key, 'HREADYOUT'), 'input')) template_ports += [ Port('{0}_{1}'.format(key, 'HREADY'), '{0}_{1}'.format(key, 'HREADY')) ] template_ports += [ Port('{0}_{1}'.format(key, 'HREADYOUT'), '{0}_{1}'.format(key, 'HREADYOUT')) ] # Generate master assignments for key, val in self.masters.items(): self.verilog_writer.add( Assign('mst_{0} [{1}]'.format('priority', val.index), val.priority)) for p in AHB3_MASTER_PORTS: self.verilog_writer.add( Assign('mst_{0} [{1}]'.format(p.name, val.index), '{0}_{1}'.format(key, p.name))) for p in AHB3_SLAVE_PORTS: self.verilog_writer.add( Assign('{0}_{1}'.format(key, p.name), 'mst_{0} [{1}]'.format(p.name, val.index))) # Add HREADY assignments self.verilog_writer.add( Assign('mst_{0} [{1}]'.format('HREADY', val.index), 'mst_{0} [{1}]'.format('HREADYOUT', val.index))) self.verilog_writer.add( Assign('{0}_{1}'.format(key, 'HREADY'), 'mst_{0} [{1}]'.format('HREADYOUT', val.index))) # Generate slave assignments for key, val in self.slaves.items(): self.verilog_writer.add( Assign('slv_addr_base [{0}]'.format(val.index), val.offset, width=32)) self.verilog_writer.add( Assign('slv_addr_mask [{0}]'.format(val.index), ~(val.size - 1), width=32)) for p in AHB3_MASTER_PORTS: self.verilog_writer.add( Assign('{0}_{1}'.format(key, p.name), 'slv_{0} [{1}]'.format(p.name, val.index))) for p in AHB3_SLAVE_PORTS: self.verilog_writer.add( Assign('slv_{0} [{1}]'.format(p.name, val.index), '{0}_{1}'.format(key, p.name))) # Add HREADY assignments self.verilog_writer.add( Assign('slv_{0} [{1}]'.format('HREADY', val.index), '{0}_{1}'.format(key, 'HREADYOUT'))) self.verilog_writer.add( Assign('{0}_{1}'.format(key, 'HREADY'), 'slv_{0} [{1}]'.format('HREADYOUT', val.index))) # Instantiate interconnect inter_param = [ Parameter('MASTERS', len(self.masters)), Parameter('SLAVES', len(self.slaves)), Parameter('HADDR_SIZE', 32), Parameter('HDATA_SIZE', 32), Parameter('MASTER_BITS', 'MASTER_BITS'), ] inter_ports = [ Port('HCLK', 'clk'), Port('HRESETn', 'reset_n'), Port('mst_priority', 'mst_priority'), Port('slv_addr_base', 'slv_addr_base'), Port('slv_addr_mask', 'slv_addr_mask'), Port('mst_HREADY', 'mst_HREADY'), Port('slv_HREADY', 'slv_HREADY'), Port('mst_HREADYOUT', 'mst_HREADYOUT'), Port('slv_HREADYOUT', 'slv_HREADYOUT'), ] inter_ports += [ Port('mst_' + p.name, 'mst_' + p.name) for p in AHB3_MASTER_PORTS ] inter_ports += [ Port('slv_' + p.name, 'slv_' + p.name) for p in AHB3_MASTER_PORTS ] inter_ports += [ Port('mst_' + p.name, 'mst_' + p.name) for p in AHB3_SLAVE_PORTS ] inter_ports += [ Port('slv_' + p.name, 'slv_' + p.name) for p in AHB3_SLAVE_PORTS ] self.verilog_writer.add( Instance('ahb3lite_interconnect', 'ahb3lite_intercon0', inter_param, inter_ports)) # Create template self.template_writer.add( Instance(self.name, self.name + '0', template_parameters, template_ports)) self.verilog_writer.write(file) self.template_writer.write(file[:-2] + 'vh') core_file = self.vlnv.split(':')[2] + '.core' vlnv = self.vlnv with open(core_file, 'w') as f: f.write('CAPI=2:\n') files = [{ file: { 'file_type': 'verilogSource' } }, { file[:-2] + 'vh': { 'is_include_file': True, 'file_type': 'verilogSource' } }] coredata = { 'name': vlnv, 'targets': { 'default': {} }, } coredata['filesets'] = {'rtl': {'files': files}} coredata['targets']['default']['filesets'] = ['rtl'] f.write(yaml.dump(coredata))
def gen_junctions_top(self, config): junctions = VerilogWriter('junctions') junctions.add(ModulePort('i_clk', 'input')) junctions.add(ModulePort('i_rst', 'input')) i = 0 muxports = [Port('clk', 'i_clk'), Port('rst', 'i_rst')] for name, data in config.items(): collector = None if data: collector = data.get('collector') junction_ports = [ Port('i_clk', 'i_clk'), Port('i_rst', 'i_rst'), ] if collector == 'gpio': junction_ports += [ Port('i_gpio', 'i_' + name + '_gpio'), ] elif collector == 'spi': junction_ports += [ Port('o_sclk', 'o_' + name + '_sclk'), Port('o_cs_n', 'o_' + name + '_cs_n'), Port('o_mosi', 'o_' + name + '_mosi'), Port('i_miso', 'i_' + name + '_miso'), ] junction_ports += [ Port('o_tdata', 'tdata' + str(i)), Port('o_tlast', 'tlast' + str(i)), Port('o_tvalid', 'tvalid' + str(i)), Port('i_tready', 'tready' + str(i)), ] junctions.add( Instance(name, 'junction_' + name, [], junction_ports)) if collector == 'gpio': junctions.add(ModulePort('i_' + name + '_gpio', 'input')) elif collector == 'spi': junctions.add(ModulePort('o_' + name + '_sclk', 'output')) junctions.add(ModulePort('o_' + name + '_cs_n', 'output')) junctions.add(ModulePort('o_' + name + '_mosi', 'output')) junctions.add(ModulePort('i_' + name + '_miso', 'input')) junctions.add(Wire('tdata' + str(i), 8)) junctions.add(Wire('tlast' + str(i))) junctions.add(Wire('tvalid' + str(i))) junctions.add(Wire('tready' + str(i))) muxports += [ Port("s{:02}_axis_tdata".format(i), 'tdata' + str(i)), Port("s{:02}_axis_tkeep".format(i), "1'b0"), Port("s{:02}_axis_tvalid".format(i), 'tvalid' + str(i)), Port("s{:02}_axis_tready".format(i), 'tready' + str(i)), Port("s{:02}_axis_tlast".format(i), 'tlast' + str(i)), Port("s{:02}_axis_tid".format(i), "8'd0"), Port("s{:02}_axis_tdest".format(i), "8'd0"), Port("s{:02}_axis_tuser".format(i), "1'b0"), ] i += 1 junctions.add(ModulePort('o_tdata', 'output', 8)) junctions.add(ModulePort('o_tlast', 'output')) junctions.add(ModulePort('o_tvalid', 'output')) junctions.add(ModulePort('i_tready', 'input')) muxports += [ Port('m_axis_tdata ', 'o_tdata'), Port('m_axis_tkeep ', ''), Port('m_axis_tvalid', 'o_tvalid'), Port('m_axis_tready', 'i_tready'), Port('m_axis_tlast ', 'o_tlast'), Port('m_axis_tid ', ''), Port('m_axis_tdest ', ''), Port('m_axis_tuser ', ''), ] junctions.add( Instance('bcmux', 'bcmux', [ Parameter('USER_ENABLE', '0'), Parameter('ARB_TYPE', '"ROUND_ROBIN"') ], muxports)) junctions.write('junctions.v')
def junction_top(self, name, collector, memfile): junction_top = VerilogWriter(name) junction_top.add(ModulePort('i_clk', 'input')) junction_top.add(ModulePort('i_rst', 'input')) if collector == 'gpio': junction_top.add(ModulePort('i_gpio', 'input')) junction_top.add(Wire('wb_stb')) junction_top.add(Wire('wb_rdt')) junction_top.add(Wire('wb_ack')) junction_top.add( Instance('collector_gpio', 'gpio', [], [ Port('i_clk', 'i_clk'), Port('i_rst', 'i_rst'), Port('i_dat', 'i_gpio'), Port('i_wb_stb', 'wb_stb'), Port('o_wb_rdt', 'wb_rdt'), Port('o_wb_ack', 'wb_ack'), ])) elif collector == 'spi': junction_top.add(ModulePort('o_sclk', 'output')) junction_top.add(ModulePort('o_cs_n', 'output')) junction_top.add(ModulePort('o_mosi', 'output')) junction_top.add(ModulePort('i_miso', 'input')) junction_top.add(Wire('wb_adr', 32)) junction_top.add(Wire('wb_dat', 32)) junction_top.add(Wire('wb_we')) junction_top.add(Wire('wb_stb')) junction_top.add(Wire('wb_rdt', 32)) junction_top.add(Wire('wb_ack')) junction_top.add( Instance('collector_spi', 'spi', [], [ Port('i_clk', 'i_clk'), Port('i_rst', 'i_rst'), Port('o_sclk', 'o_sclk'), Port('o_cs_n', 'o_cs_n'), Port('o_mosi', 'o_mosi'), Port('i_miso', 'i_miso'), Port('i_wb_adr', 'wb_adr[4:0]'), Port('i_wb_dat', 'wb_dat'), Port('i_wb_we', 'wb_we'), Port('i_wb_stb', 'wb_stb'), Port('o_wb_rdt', 'wb_rdt'), Port('o_wb_ack', 'wb_ack'), ])) junction_top.add(ModulePort('o_tdata', 'output', 8)) junction_top.add(ModulePort('o_tlast', 'output')) junction_top.add(ModulePort('o_tvalid', 'output')) junction_top.add(ModulePort('i_tready', 'input')) ports = [ Port('i_clk', 'i_clk'), Port('i_rst', 'i_rst'), ] if collector == 'spi': ports += [ Port('o_wb_coll_adr', 'wb_adr'), Port('o_wb_coll_dat', 'wb_dat'), Port('o_wb_coll_we', 'wb_we'), ] else: ports += [ Port('o_wb_coll_adr', ''), Port('o_wb_coll_dat', ''), Port('o_wb_coll_we', ''), ] if collector: ports.append(Port('o_wb_coll_stb', 'wb_stb')) else: ports.append(Port('o_wb_coll_stb', '')) if collector == 'gpio': ports.append(Port('i_wb_coll_rdt', "{31'd0,wb_rdt}")) elif collector == 'spi': ports.append(Port('i_wb_coll_rdt', 'wb_rdt')) else: ports.append(Port('i_wb_coll_rdt', "32'd0")) if collector: ports.append(Port('i_wb_coll_ack', 'wb_ack')) else: ports.append(Port('i_wb_coll_ack', "1'b0")) ports += [ Port('o_tdata', 'o_tdata'), Port('o_tlast', 'o_tlast'), Port('o_tvalid', 'o_tvalid'), Port('i_tready', 'i_tready'), ] junction_top.add( Instance('base', 'base', [Parameter('memfile', '"' + memfile + '"')], ports)) junction_top.write(os.path.join(name, 'junction.v'))
class WbIntercon: def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name) self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() config = configparser.SafeConfigParser() config.read(config_file) for section in config.sections(): type = section.split()[0] try: name = section.split()[1] except IndexError: print( "Malformed section header. Format is master|slave <name>") exit(1) if type == "master": print("Found master " + name) self.masters[name] = Master(name, dict(config.items(section))) d[name] = config.get(section, 'slaves').split() elif type == "slave": print("Found slave " + name) self.slaves[name] = Slave(name, dict(config.items(section))) else: print("Invalid section type " + type) exit(1) #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]] def _dump(self): print("*Masters*") for master in self.masters.values(): print(master.name) for slave in master.slaves: print(' ' + slave.name) print("*Slaves*") for slave in self.slaves.values(): print(slave.name) for master in slave.masters: print(' ' + master.name) def _gen_mux(self, master): parameters = [Parameter('num_slaves', len(master.slaves))] match_addr = '{' + ', '.join( ["32'h{addr:08x}".format(addr=s.offset) for s in master.slaves]) + '}' parameters += [Parameter('MATCH_ADDR', match_addr)] match_mask = '{' + ', '.join( ["32'h{mask:08x}".format(mask=s.mask) for s in master.slaves]) + '}' parameters += [Parameter('MATCH_MASK', match_mask)] ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] m = master.name # If we are converting bus type, do not use _i / _o if master.bus_type == 'wishbone': input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' else: # We're the slave to the conversion logic input_format = 'wb_m2s_%s_%s' output_format = 'wb_s2m_%s_%s' #Create mux master side connections for p in WB_MASTER_PORTS: ports += [Port('wbm_' + p.name + '_i', input_format % (m, p.name))] for p in WB_SLAVE_PORTS: ports += [ Port('wbm_' + p.name + '_o', output_format % (m, p.name)) ] #Create mux slave side connections name_list = [] for s in master.slaves: #If we have only one master the wb_mux is the last piece before #the slave. If the slave's datawidth is 32, we go straight from #the wb_mux to the slave. if len(s.masters) == 1 and int(s.datawidth) == 32: name_list += ['wb_' + s.name + '_{0}_{1}'] #If not, we'll need a wb_data_resize and then new wires. elif len(s.masters) == 1 and int(s.datawidth) < 32: name_list += ['wb_{dir}' + 'resize_' + s.name + '_{0}'] #If there is more than on master for that slave, there will #be an arbiter and the wb_data_resize will be after that. else: name_list += ['wb_{dir}' + m + '_' + s.name + '_{0}'] for p in WB_MASTER_PORTS: ports += [ Port( 'wbs_' + p.name + '_o', '{' + ', '.join(name_list).format(p.name, 'o', dir='m2s_') + '}') ] for p in WB_SLAVE_PORTS: ports += [ Port( 'wbs_' + p.name + '_i', '{' + ', '.join(name_list).format(p.name, 'i', dir='s2m_') + '}') ] self.verilog_writer.add( Instance('wb_mux', 'wb_mux_' + m, parameters, ports)) def _gen_arbiter(self, slave): parameters = [Parameter('num_masters', len(slave.masters))] ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] s = slave.name name_list = [] for m in slave.masters: name_list += ['wb_{dir}' + m.name + '_' + s + '_{0}'] for p in WB_MASTER_PORTS: ports += [ Port( 'wbm_' + p.name + '_i', '{' + ', '.join(name_list).format(p.name, 'i', dir='m2s_') + '}') ] for p in WB_SLAVE_PORTS: ports += [ Port( 'wbm_' + p.name + '_o', '{' + ', '.join(name_list).format(p.name, 'o', dir='s2m_') + '}') ] #Create slave connections #If the slave's data width is 32, we don't need a wb_data_resize if int(slave.datawidth) == 32: # If we are converting bus type, do not use _i / _o if slave.bus_type == 'wishbone': input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' else: input_format = 'wb_s2m_%s_%s' output_format = 'wb_m2s_%s_%s' for p in WB_MASTER_PORTS: ports += [ Port('wbs_' + p.name + '_o', output_format % (s, p.name)) ] for p in WB_SLAVE_PORTS: ports += [ Port('wbs_' + p.name + '_i', input_format % (s, p.name)) ] #Else, connect to the resizer else: for p in WB_MASTER_PORTS: ports += [ Port('wbs_' + p.name + '_o', 'wb_m2s_resize_' + s + '_' + p.name) ] for p in WB_SLAVE_PORTS: ports += [ Port('wbs_' + p.name + '_i', 'wb_s2m_resize_' + s + '_' + p.name) ] self.verilog_writer.add( Instance('wb_arbiter', 'wb_arbiter_' + s, parameters, ports)) def _gen_resize(self, slave): parameters = [Parameter('aw', 32)] parameters += [Parameter('mdw', 32)] parameters += [Parameter('sdw', slave.datawidth)] s = slave.name ports = [] #Create master connections for p in WB_MASTER_PORTS: ports += [ Port('wbm_' + p.name + '_i', 'wb_m2s_resize_' + s + '_' + p.name) ] for p in WB_SLAVE_PORTS: ports += [ Port('wbm_' + p.name + '_o', 'wb_s2m_resize_' + s + '_' + p.name) ] # If we are converting bus type, do not use _i / _o if slave.bus_type == 'wishbone': input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' else: input_format = 'wb_s2m_%s_%s' output_format = 'wb_m2s_%s_%s' #Create slave connections for p in WB_MASTER_PORTS: if p.name != "sel": ports.append( Port('wbs_' + p.name + '_o', output_format % (s, p.name))) for p in WB_SLAVE_PORTS: ports.append( Port('wbs_' + p.name + '_i', input_format % (s, p.name))) self.verilog_writer.add( Instance('wb_data_resize', 'wb_data_resize_' + s, parameters, ports)) for p in WB_MASTER_PORTS: wirename = 'wb_m2s_resize_{slave}_{port}'.format(slave=s, port=p.name) self.verilog_writer.add(Wire(wirename, p.width)) for p in WB_SLAVE_PORTS: wirename = 'wb_s2m_resize_{slave}_{port}'.format(slave=s, port=p.name) self.verilog_writer.add(Wire(wirename, p.width)) def _gen_wishbone_master_port(self, master): template_ports = [] for p in WB_MASTER_PORTS: portname = 'wb_{master}_{port}_i'.format(master=master.name, port=p.name) wirename = 'wb_m2s_{master}_{port}'.format(master=master.name, port=p.name) self.verilog_writer.add(ModulePort(portname, 'input', p.width)) self.template_writer.add(Wire(wirename, p.width)) template_ports += [Port(portname, wirename)] for p in WB_SLAVE_PORTS: portname = 'wb_{master}_{port}_o'.format(master=master.name, port=p.name) wirename = 'wb_s2m_{master}_{port}'.format(master=master.name, port=p.name) self.verilog_writer.add(ModulePort(portname, 'output', p.width)) self.template_writer.add(Wire(wirename, p.width)) template_ports += [Port(portname, wirename)] return template_ports def _gen_wishbone_port(self, slave): template_ports = [] for p in WB_MASTER_PORTS: portname = 'wb_{slave}_{port}_o'.format(slave=slave.name, port=p.name) wirename = 'wb_m2s_{slave}_{port}'.format(slave=slave.name, port=p.name) dw = int(WB_DATA_WIDTH[p.name] * slave.datawidth) or p.width self.verilog_writer.add(ModulePort(portname, 'output', dw)) self.template_writer.add(Wire(wirename, dw)) template_ports += [Port(portname, wirename)] for p in WB_SLAVE_PORTS: portname = 'wb_{slave}_{port}_i'.format(slave=slave.name, port=p.name) wirename = 'wb_s2m_{slave}_{port}'.format(slave=slave.name, port=p.name) dw = int(WB_DATA_WIDTH[p.name] * slave.datawidth) or p.width self.verilog_writer.add(ModulePort(portname, 'input', dw)) self.template_writer.add(Wire(wirename, dw)) template_ports += [Port(portname, wirename)] return template_ports def _gen_bus_converter(self, bus, name, is_master, datawidth, datawidth_map, ports): converter_ports = [ Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i') ] template_ports = [] out_direction = 'm2s' if is_master else 's2m' # Wishbone side ms_type = 'm' if is_master else 's' # Foreign side f_ms_type = 's' if is_master else 'm' # Create Wishbone connections wb_ports = [] wb_ports.extend([(p, 'm2s') for p in WB_MASTER_PORTS]) wb_ports.extend([(p, 's2m') for p in WB_SLAVE_PORTS]) for p, direction in wb_ports: pin_direction = 'output' if direction == out_direction else 'input' wirename = 'wb_{direction}_{name}_{port}'.format( direction=direction, name=name, port=p.name) converter_ports.append( Port( '%s_%s_%s' % ('wbm' if ms_type == 'm' else 'wb', p.name, pin_direction[0]), wirename)) dw = int(WB_DATA_WIDTH[p.name] * datawidth) or p.width self.verilog_writer.add(Wire(wirename, dw)) # Create foreign bus connections for p, direction in ports: pin_direction = 'output' if direction != out_direction else 'input' portname = '{d}_{bus}_{name}_{port}_{direction}'.format( d=f_ms_type, bus=bus, direction=pin_direction[0], name=name, port=p.name) wirename = '{bus}_{direction}_{name}_{port}'.format( bus=bus, direction=direction, name=name, port=p.name) converter_ports.append( Port( '{d}_{bus}_{port}_{direction}'.format( d=f_ms_type, bus=bus, direction=pin_direction[0], port=p.name), portname)) dw = int(datawidth_map[p.name] * datawidth) or p.width self.verilog_writer.add( ModulePort(portname, pin_direction, p.width)) self.template_writer.add(Wire(wirename, dw)) template_ports.append(Port(portname, wirename)) return template_ports, converter_ports def _gen_axi4_port(self, thing, is_master=False): parameters = [ Parameter('C_AXI_ADDR_WIDTH', 32), Parameter('C_S_AXI_DATA_WIDTH', thing.datawidth) ] ports = [] ports.extend([(p, 'm2s') for p in AXI4_MASTER_PORTS]) ports.extend([(p, 's2m') for p in AXI4_SLAVE_PORTS]) if thing.bus_type == 'axi4-lite': ports = [p for p in ports if p[0].name in AXI4_LITE_PORTS] template_ports, converter_ports = self._gen_bus_converter( 'axi', name=thing.name, is_master=is_master, datawidth=thing.datawidth, datawidth_map=AXI4_DATA_WIDTH, ports=ports) core = 'wb_axi_slave' if is_master else 'wb_axi_master' self.verilog_writer.add( Instance(core, '%s_%s' % (core, thing.name), parameters, converter_ports)) return template_ports def _gen_avalon_port(self, thing, is_master=False): parameters = [Parameter('AW', 32), Parameter('DW', thing.datawidth)] if not is_master: parameters.append(Parameter('BURST_SUPPORT', 1)) ports = [] ports.extend([(p, 'm2s') for p in AVALON_MASTER_PORTS]) ports.extend([(p, 's2m') for p in AVALON_SLAVE_PORTS]) template_ports, converter_ports = self._gen_bus_converter( 'av', name=thing.name, is_master=is_master, datawidth=thing.datawidth, datawidth_map=AVALON_DATA_WIDTH, ports=ports) core = 'avalon_to_wb_bridge' if is_master else 'wb_to_avalon_bridge' self.verilog_writer.add( Instance(core, '%s_%s' % (core, thing.name), parameters, converter_ports)) return template_ports def write(self, file): #Declare wires. Only conections between muxes and arbiters need explicit wires for key, value in self.masters.items(): for slave in value.slaves: if len(slave.masters) > 1: for p in WB_MASTER_PORTS: self.verilog_writer.add( Wire( 'wb_m2s_{0}_{1}_{2}'.format( key, slave.name, p.name), p.width)) for p in WB_SLAVE_PORTS: self.verilog_writer.add( Wire( 'wb_s2m_{0}_{1}_{2}'.format( key, slave.name, p.name), p.width)) self.verilog_writer.add(ModulePort('wb_clk_i', 'input')) self.verilog_writer.add(ModulePort('wb_rst_i', 'input')) template_ports = [ Port('wb_clk_i', 'wb_clk'), Port('wb_rst_i', 'wb_rst') ] template_parameters = [] for master in self.masters.values(): self._gen_mux(master) if master.bus_type == 'wishbone': master_template_ports = self._gen_wishbone_master_port(master) elif master.bus_type.startswith('axi4'): master_template_ports = self._gen_axi4_port(master, is_master=True) elif master.bus_type == 'avalon': master_template_ports = self._gen_avalon_port(master, is_master=True) template_ports.extend(master_template_ports) for slave in self.slaves.values(): if len(slave.masters) > 1: self._gen_arbiter(slave) if int(slave.datawidth) < 32: self._gen_resize(slave) if slave.bus_type == 'wishbone': slave_template_ports = self._gen_wishbone_port(slave) elif slave.bus_type.startswith('axi4'): slave_template_ports = self._gen_axi4_port(slave) elif slave.bus_type == 'avalon': slave_template_ports = self._gen_avalon_port(slave) template_ports.extend(slave_template_ports) self.template_writer.add( Instance(self.name, self.name + '0', template_parameters, template_ports)) self.verilog_writer.write(file) self.template_writer.write(file + 'h')
class WbIntercon: def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name); self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() config = configparser.SafeConfigParser() config.read(config_file) for section in config.sections(): type=section.split()[0] try: name=section.split()[1] except IndexError: print("Malformed section header. Format is master|slave <name>") exit(1) if type == "master": print("Found master " + name) self.masters[name] = Master(name, dict(config.items(section))) d[name] = config.get(section, 'slaves').split() elif type == "slave": print("Found slave " + name) self.slaves[name] = Slave(name, dict(config.items(section))) else: print("Invalid section type " + type) exit(1) #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]] def _dump(self): print("*Masters*") for master in self.masters.values(): print(master.name) for slave in master.slaves: print(' ' + slave.name) print("*Slaves*") for slave in self.slaves.values(): print(slave.name) for master in slave.masters: print(' ' + master.name) def _gen_mux(self, master): parameters = [Parameter('num_slaves', len(master.slaves))] match_addr = '{' + ', '.join(["32'h{addr:08x}".format(addr=s.offset) for s in master.slaves]) + '}' parameters += [Parameter('MATCH_ADDR', match_addr)] match_mask = '{' + ', '.join(["32'h{mask:08x}".format(mask=s.mask) for s in master.slaves]) + '}' parameters += [Parameter('MATCH_MASK', match_mask)] ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] m = master.name # If we are converting bus type, do not use _i / _o if master.bus_type == 'wishbone': input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' else: # We're the slave to the conversion logic input_format = 'wb_m2s_%s_%s' output_format = 'wb_s2m_%s_%s' #Create mux master side connections for p in WB_MASTER_PORTS: ports += [Port('wbm_' + p.name + '_i', input_format % (m, p.name))] for p in WB_SLAVE_PORTS: ports += [Port('wbm_' + p.name + '_o', output_format % (m, p.name))] #Create mux slave side connections name_list = [] for s in master.slaves: #If we have only one master the wb_mux is the last piece before #the slave. If the slave's datawidth is 32, we go straight from #the wb_mux to the slave. if len(s.masters) == 1 and int(s.datawidth) == 32: name_list += ['wb_' + s.name + '_{0}_{1}'] #If not, we'll need a wb_data_resize and then new wires. elif len(s.masters) == 1 and int(s.datawidth) < 32: name_list += ['wb_{dir}' + 'resize_' + s.name + '_{0}'] #If there is more than on master for that slave, there will #be an arbiter and the wb_data_resize will be after that. else: name_list += ['wb_{dir}'+ m + '_' + s.name + '_{0}'] for p in WB_MASTER_PORTS: ports += [Port('wbs_'+p.name+'_o', '{' + ', '.join(name_list).format(p.name, 'o', dir='m2s_')+'}')] for p in WB_SLAVE_PORTS: ports += [Port('wbs_'+p.name+'_i', '{' + ', '.join(name_list).format(p.name, 'i', dir='s2m_')+'}')] self.verilog_writer.add(Instance('wb_mux', 'wb_mux_'+m,parameters, ports)) def _gen_arbiter(self, slave): parameters = [Parameter('num_masters', len(slave.masters))] ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] s = slave.name name_list = [] for m in slave.masters: name_list += ['wb_{dir}'+ m.name + '_' + s + '_{0}'] for p in WB_MASTER_PORTS: ports += [Port('wbm_'+p.name+'_i', '{' + ', '.join(name_list).format(p.name, 'i', dir='m2s_')+'}')] for p in WB_SLAVE_PORTS: ports += [Port('wbm_'+p.name+'_o', '{' + ', '.join(name_list).format(p.name, 'o', dir='s2m_')+'}')] #Create slave connections #If the slave's data width is 32, we don't need a wb_data_resize if int(slave.datawidth) == 32: # If we are converting bus type, do not use _i / _o if slave.bus_type == 'wishbone': input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' else: input_format = 'wb_s2m_%s_%s' output_format = 'wb_m2s_%s_%s' for p in WB_MASTER_PORTS: ports += [Port('wbs_' + p.name + '_o', output_format % (s, p.name))] for p in WB_SLAVE_PORTS: ports += [Port('wbs_' + p.name + '_i', input_format % (s, p.name))] #Else, connect to the resizer else: for p in WB_MASTER_PORTS: ports += [Port('wbs_' + p.name + '_o', 'wb_m2s_resize_'+s+'_'+p.name)] for p in WB_SLAVE_PORTS: ports += [Port('wbs_' + p.name + '_i', 'wb_s2m_resize_'+s+'_'+p.name)] self.verilog_writer.add(Instance('wb_arbiter', 'wb_arbiter_'+s,parameters, ports)) def _gen_resize(self, slave): parameters = [Parameter('aw', 32)] parameters += [Parameter('mdw', 32)] parameters += [Parameter('sdw', slave.datawidth)] s = slave.name ports =[] #Create master connections for p in WB_MASTER_PORTS: ports += [Port('wbm_'+p.name+'_i', 'wb_m2s_resize_'+s+'_'+p.name)] for p in WB_SLAVE_PORTS: ports += [Port('wbm_'+p.name+'_o', 'wb_s2m_resize_'+s+'_'+p.name)] # If we are converting bus type, do not use _i / _o if slave.bus_type == 'wishbone': input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' else: input_format = 'wb_s2m_%s_%s' output_format = 'wb_m2s_%s_%s' #Create slave connections for p in WB_MASTER_PORTS: if p.name != "sel": ports.append(Port('wbs_' + p.name + '_o', output_format % (s, p.name))) for p in WB_SLAVE_PORTS: ports.append(Port('wbs_' + p.name + '_i', input_format % (s, p.name))) self.verilog_writer.add(Instance('wb_data_resize', 'wb_data_resize_'+s,parameters, ports)) for p in WB_MASTER_PORTS: wirename = 'wb_m2s_resize_{slave}_{port}'.format(slave=s, port=p.name) self.verilog_writer.add(Wire(wirename, p.width)) for p in WB_SLAVE_PORTS: wirename = 'wb_s2m_resize_{slave}_{port}'.format(slave=s, port=p.name) self.verilog_writer.add(Wire(wirename, p.width)) def _gen_wishbone_master_port(self, master): template_ports = [] for p in WB_MASTER_PORTS: portname = 'wb_{master}_{port}_i'.format(master=master.name, port=p.name) wirename = 'wb_m2s_{master}_{port}'.format(master=master.name, port=p.name) self.verilog_writer.add(ModulePort(portname, 'input', p.width)) self.template_writer.add(Wire(wirename, p.width)) template_ports += [Port(portname, wirename)] for p in WB_SLAVE_PORTS: portname = 'wb_{master}_{port}_o'.format(master=master.name, port=p.name) wirename = 'wb_s2m_{master}_{port}'.format(master=master.name, port=p.name) self.verilog_writer.add(ModulePort(portname, 'output', p.width)) self.template_writer.add(Wire(wirename, p.width)) template_ports += [Port(portname, wirename)] return template_ports def _gen_wishbone_port(self, slave): template_ports = [] for p in WB_MASTER_PORTS: portname = 'wb_{slave}_{port}_o'.format(slave=slave.name, port=p.name) wirename = 'wb_m2s_{slave}_{port}'.format(slave=slave.name, port=p.name) dw = int(WB_DATA_WIDTH[p.name] * slave.datawidth) or p.width self.verilog_writer.add(ModulePort(portname, 'output', dw)) self.template_writer.add(Wire(wirename, dw)) template_ports += [Port(portname, wirename)] for p in WB_SLAVE_PORTS: portname = 'wb_{slave}_{port}_i'.format(slave=slave.name, port=p.name) wirename = 'wb_s2m_{slave}_{port}'.format(slave=slave.name, port=p.name) dw = int(WB_DATA_WIDTH[p.name] * slave.datawidth) or p.width self.verilog_writer.add(ModulePort(portname, 'input', dw)) self.template_writer.add(Wire(wirename, dw)) template_ports += [Port(portname, wirename)] return template_ports def _gen_bus_converter(self, bus, name, is_master, datawidth, datawidth_map, ports): converter_ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] template_ports = [] out_direction = 'm2s' if is_master else 's2m' # Wishbone side ms_type = 'm' if is_master else 's' # Foreign side f_ms_type = 's' if is_master else 'm' # Create Wishbone connections wb_ports = [] wb_ports.extend([(p, 'm2s') for p in WB_MASTER_PORTS]) wb_ports.extend([(p, 's2m') for p in WB_SLAVE_PORTS]) for p, direction in wb_ports: pin_direction = 'output' if direction == out_direction else 'input' wirename = 'wb_{direction}_{name}_{port}'.format( direction=direction, name=name, port=p.name) converter_ports.append( Port('%s_%s_%s' % ('wbm' if ms_type == 'm' else 'wb', p.name, pin_direction[0]), wirename)) dw = int(WB_DATA_WIDTH[p.name] * datawidth) or p.width self.verilog_writer.add(Wire(wirename, dw)) # Create foreign bus connections for p, direction in ports: pin_direction = 'output' if direction != out_direction else 'input' portname = '{d}_{bus}_{name}_{port}_{direction}'.format( d=f_ms_type, bus=bus, direction=pin_direction[0], name=name, port=p.name) wirename = '{bus}_{direction}_{name}_{port}'.format( bus=bus, direction=direction, name=name, port=p.name) converter_ports.append( Port('{d}_{bus}_{port}_{direction}'.format( d=f_ms_type, bus=bus, direction=pin_direction[0], port=p.name), portname)) dw = int(datawidth_map[p.name] * datawidth) or p.width self.verilog_writer.add( ModulePort(portname, pin_direction, p.width)) self.template_writer.add(Wire(wirename, dw)) template_ports.append(Port(portname, wirename)) return template_ports, converter_ports def _gen_axi4_port(self, thing, is_master=False): parameters = [Parameter('C_AXI_ADDR_WIDTH', 32), Parameter('C_S_AXI_DATA_WIDTH', thing.datawidth)] ports = [] ports.extend([(p, 'm2s') for p in AXI4_MASTER_PORTS]) ports.extend([(p, 's2m') for p in AXI4_SLAVE_PORTS]) if thing.bus_type == 'axi4-lite': ports = [p for p in ports if p[0].name in AXI4_LITE_PORTS] template_ports, converter_ports = self._gen_bus_converter( 'axi', name=thing.name, is_master=is_master, datawidth=thing.datawidth, datawidth_map=AXI4_DATA_WIDTH, ports=ports) core = 'wb_axi_slave' if is_master else 'wb_axi_master' self.verilog_writer.add(Instance( core, '%s_%s' % (core, thing.name), parameters, converter_ports)) return template_ports def _gen_avalon_port(self, thing, is_master=False): parameters = [Parameter('AW', 32), Parameter('DW', thing.datawidth)] if not is_master: parameters.append(Parameter('BURST_SUPPORT', 1)) ports = [] ports.extend([(p, 'm2s') for p in AVALON_MASTER_PORTS]) ports.extend([(p, 's2m') for p in AVALON_SLAVE_PORTS]) template_ports, converter_ports = self._gen_bus_converter( 'av', name=thing.name, is_master=is_master, datawidth=thing.datawidth, datawidth_map=AVALON_DATA_WIDTH, ports=ports) core = 'avalon_to_wb_bridge' if is_master else 'wb_to_avalon_bridge' self.verilog_writer.add(Instance( core, '%s_%s' % (core, thing.name), parameters, converter_ports)) return template_ports def write(self, file): #Declare wires. Only conections between muxes and arbiters need explicit wires for key, value in self.masters.items(): for slave in value.slaves: if len(slave.masters)>1: for p in WB_MASTER_PORTS: self.verilog_writer.add(Wire('wb_m2s_{0}_{1}_{2}'.format(key, slave.name, p.name), p.width)) for p in WB_SLAVE_PORTS: self.verilog_writer.add(Wire('wb_s2m_{0}_{1}_{2}'.format(key, slave.name, p.name), p.width)) self.verilog_writer.add(ModulePort('wb_clk_i', 'input')) self.verilog_writer.add(ModulePort('wb_rst_i', 'input')) template_ports = [Port('wb_clk_i', 'wb_clk'), Port('wb_rst_i', 'wb_rst')] template_parameters = [] for master in self.masters.values(): self._gen_mux(master) if master.bus_type == 'wishbone': master_template_ports = self._gen_wishbone_master_port(master) elif master.bus_type.startswith('axi4'): master_template_ports = self._gen_axi4_port( master, is_master=True) elif master.bus_type == 'avalon': master_template_ports = self._gen_avalon_port( master, is_master=True) template_ports.extend(master_template_ports) for slave in self.slaves.values(): if len(slave.masters) > 1: self._gen_arbiter(slave) if int(slave.datawidth) < 32: self._gen_resize(slave) if slave.bus_type == 'wishbone': slave_template_ports = self._gen_wishbone_port(slave) elif slave.bus_type.startswith('axi4'): slave_template_ports = self._gen_axi4_port(slave) elif slave.bus_type == 'avalon': slave_template_ports = self._gen_avalon_port(slave) template_ports.extend(slave_template_ports) self.template_writer.add(Instance(self.name, self.name+'0', template_parameters, template_ports)) self.verilog_writer.write(file) self.template_writer.write(file+'h')
class WbIntercon: def __init__(self, name, config_file): self.verilog_writer = VerilogWriter(name) self.template_writer = VerilogWriter(name); self.name = name d = OrderedDict() self.slaves = OrderedDict() self.masters = OrderedDict() import yaml def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): class OrderedLoader(Loader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return object_pairs_hook(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) return yaml.load(stream, OrderedLoader) data = ordered_load(open(config_file)) config = data['parameters'] files_root = data['files_root'] self.vlnv = data['vlnv'] valid_endians = ['big', 'little'] if 'endian' in config: self.endian = config['endian'] if self.endian not in valid_endians: raise UnknownPropertyError("Unknown data resizer endian '{}' specified. Valid endians: {}".format(config['endian'], valid_endians)) else: self.endian = "big" print("Wishbone Data Resizer Endian: {}".format(config['endian'])) for k,v in config['masters'].items(): print("Found master " + k) self.masters[k] = Master(k,v) d[k] = v['slaves'] for k,v in config['slaves'].items(): print("Found slave " + k) self.slaves[k] = Slave(k,v) #Create master/slave connections for master, slaves in d.items(): for slave in slaves: self.masters[master].slaves += [self.slaves[slave]] self.slaves[slave].masters += [self.masters[master]] self.output_file = config.get('output_file', 'wb_intercon.v') def _dump(self): print("*Masters*") for master in self.masters.values(): print(master.name) for slave in master.slaves: print(' ' + slave.name) print("*Slaves*") for slave in self.slaves.values(): print(slave.name) for master in slave.masters: print(' ' + master.name) def _gen_mux(self, master): parameters = [Parameter('num_slaves', len(master.slaves))] match_addr = '{' + ', '.join(["32'h{addr:08x}".format(addr=s.offset) for s in master.slaves]) + '}' parameters += [Parameter('MATCH_ADDR', match_addr)] match_mask = '{' + ', '.join(["32'h{mask:08x}".format(mask=s.mask) for s in master.slaves]) + '}' parameters += [Parameter('MATCH_MASK', match_mask)] ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] m = master.name input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' #Create mux master side connections for p in WB_MASTER_PORTS: ports += [Port('wbm_' + p.name + '_i', input_format % (m, p.name))] for p in WB_SLAVE_PORTS: ports += [Port('wbm_' + p.name + '_o', output_format % (m, p.name))] #Create mux slave side connections name_list = [] for s in master.slaves: #If we have only one master the wb_mux is the last piece before #the slave. If the slave's datawidth is 32, we go straight from #the wb_mux to the slave. if len(s.masters) == 1 and int(s.datawidth) == 32: name_list += ['wb_' + s.name + '_{0}_{1}'] #If not, we'll need a wb_data_resize and then new wires. elif len(s.masters) == 1 and int(s.datawidth) < 32: name_list += ['wb_{dir}' + 'resize_' + s.name + '_{0}'] #If there is more than on master for that slave, there will #be an arbiter and the wb_data_resize will be after that. else: name_list += ['wb_{dir}'+ m + '_' + s.name + '_{0}'] for p in WB_MASTER_PORTS: ports += [Port('wbs_'+p.name+'_o', '{' + ', '.join(name_list).format(p.name, 'o', dir='m2s_')+'}')] for p in WB_SLAVE_PORTS: ports += [Port('wbs_'+p.name+'_i', '{' + ', '.join(name_list).format(p.name, 'i', dir='s2m_')+'}')] self.verilog_writer.add(Instance('wb_mux', 'wb_mux_'+m,parameters, ports)) def _gen_arbiter(self, slave): parameters = [Parameter('num_masters', len(slave.masters))] ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] s = slave.name name_list = [] for m in slave.masters: name_list += ['wb_{dir}'+ m.name + '_' + s + '_{0}'] for p in WB_MASTER_PORTS: ports += [Port('wbm_'+p.name+'_i', '{' + ', '.join(name_list).format(p.name, 'i', dir='m2s_')+'}')] for p in WB_SLAVE_PORTS: ports += [Port('wbm_'+p.name+'_o', '{' + ', '.join(name_list).format(p.name, 'o', dir='s2m_')+'}')] #Create slave connections #If the slave's data width is 32, we don't need a wb_data_resize if int(slave.datawidth) == 32: input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' for p in WB_MASTER_PORTS: ports += [Port('wbs_' + p.name + '_o', output_format % (s, p.name))] for p in WB_SLAVE_PORTS: ports += [Port('wbs_' + p.name + '_i', input_format % (s, p.name))] #Else, connect to the resizer else: for p in WB_MASTER_PORTS: ports += [Port('wbs_' + p.name + '_o', 'wb_m2s_resize_'+s+'_'+p.name)] for p in WB_SLAVE_PORTS: ports += [Port('wbs_' + p.name + '_i', 'wb_s2m_resize_'+s+'_'+p.name)] self.verilog_writer.add(Instance('wb_arbiter', 'wb_arbiter_'+s,parameters, ports)) def _gen_resize(self, slave): parameters = [Parameter('aw', 32)] parameters += [Parameter('mdw', 32)] parameters += [Parameter('sdw', slave.datawidth)] parameters += [Parameter('endian', '"{}"'.format(self.endian))] s = slave.name ports =[] #Create master connections for p in WB_MASTER_PORTS: ports += [Port('wbm_'+p.name+'_i', 'wb_m2s_resize_'+s+'_'+p.name)] for p in WB_SLAVE_PORTS: ports += [Port('wbm_'+p.name+'_o', 'wb_s2m_resize_'+s+'_'+p.name)] input_format = 'wb_%s_%s_i' output_format = 'wb_%s_%s_o' #Create slave connections for p in WB_MASTER_PORTS: if p.name != "sel": ports.append(Port('wbs_' + p.name + '_o', output_format % (s, p.name))) for p in WB_SLAVE_PORTS: ports.append(Port('wbs_' + p.name + '_i', input_format % (s, p.name))) self.verilog_writer.add(Instance('wb_data_resize', 'wb_data_resize_'+s,parameters, ports)) for p in WB_MASTER_PORTS: wirename = 'wb_m2s_resize_{slave}_{port}'.format(slave=s, port=p.name) self.verilog_writer.add(Wire(wirename, p.width)) for p in WB_SLAVE_PORTS: wirename = 'wb_s2m_resize_{slave}_{port}'.format(slave=s, port=p.name) self.verilog_writer.add(Wire(wirename, p.width)) def _gen_wishbone_master_port(self, master): template_ports = [] for p in WB_MASTER_PORTS: portname = 'wb_{master}_{port}_i'.format(master=master.name, port=p.name) wirename = 'wb_m2s_{master}_{port}'.format(master=master.name, port=p.name) self.verilog_writer.add(ModulePort(portname, 'input', p.width)) self.template_writer.add(Wire(wirename, p.width)) template_ports += [Port(portname, wirename)] for p in WB_SLAVE_PORTS: portname = 'wb_{master}_{port}_o'.format(master=master.name, port=p.name) wirename = 'wb_s2m_{master}_{port}'.format(master=master.name, port=p.name) self.verilog_writer.add(ModulePort(portname, 'output', p.width)) self.template_writer.add(Wire(wirename, p.width)) template_ports += [Port(portname, wirename)] return template_ports def _gen_wishbone_port(self, slave): template_ports = [] for p in WB_MASTER_PORTS: portname = 'wb_{slave}_{port}_o'.format(slave=slave.name, port=p.name) wirename = 'wb_m2s_{slave}_{port}'.format(slave=slave.name, port=p.name) dw = int(WB_DATA_WIDTH[p.name] * slave.datawidth) or p.width self.verilog_writer.add(ModulePort(portname, 'output', dw)) self.template_writer.add(Wire(wirename, dw)) template_ports += [Port(portname, wirename)] for p in WB_SLAVE_PORTS: portname = 'wb_{slave}_{port}_i'.format(slave=slave.name, port=p.name) wirename = 'wb_s2m_{slave}_{port}'.format(slave=slave.name, port=p.name) dw = int(WB_DATA_WIDTH[p.name] * slave.datawidth) or p.width self.verilog_writer.add(ModulePort(portname, 'input', dw)) self.template_writer.add(Wire(wirename, dw)) template_ports += [Port(portname, wirename)] return template_ports def _gen_bus_converter(self, bus, name, is_master, datawidth, datawidth_map, ports): converter_ports = [Port('wb_clk_i', 'wb_clk_i'), Port('wb_rst_i', 'wb_rst_i')] template_ports = [] out_direction = 'm2s' if is_master else 's2m' # Wishbone side ms_type = 'm' if is_master else 's' # Foreign side f_ms_type = 's' if is_master else 'm' # Create Wishbone connections wb_ports = [] wb_ports.extend([(p, 'm2s') for p in WB_MASTER_PORTS]) wb_ports.extend([(p, 's2m') for p in WB_SLAVE_PORTS]) for p, direction in wb_ports: pin_direction = 'output' if direction == out_direction else 'input' wirename = 'wb_{direction}_{name}_{port}'.format( direction=direction, name=name, port=p.name) converter_ports.append( Port('%s_%s_%s' % ('wbm' if ms_type == 'm' else 'wb', p.name, pin_direction[0]), wirename)) dw = int(WB_DATA_WIDTH[p.name] * datawidth) or p.width self.verilog_writer.add(Wire(wirename, dw)) # Create foreign bus connections for p, direction in ports: pin_direction = 'output' if direction != out_direction else 'input' portname = '{d}_{bus}_{name}_{port}_{direction}'.format( d=f_ms_type, bus=bus, direction=pin_direction[0], name=name, port=p.name) wirename = '{bus}_{direction}_{name}_{port}'.format( bus=bus, direction=direction, name=name, port=p.name) converter_ports.append( Port('{d}_{bus}_{port}_{direction}'.format( d=f_ms_type, bus=bus, direction=pin_direction[0], port=p.name), portname)) dw = int(datawidth_map[p.name] * datawidth) or p.width self.verilog_writer.add( ModulePort(portname, pin_direction, p.width)) self.template_writer.add(Wire(wirename, dw)) template_ports.append(Port(portname, wirename)) return template_ports, converter_ports def write(self): file = self.output_file #Declare wires. Only conections between muxes and arbiters need explicit wires for key, value in self.masters.items(): for slave in value.slaves: if len(slave.masters)>1: for p in WB_MASTER_PORTS: self.verilog_writer.add(Wire('wb_m2s_{0}_{1}_{2}'.format(key, slave.name, p.name), p.width)) for p in WB_SLAVE_PORTS: self.verilog_writer.add(Wire('wb_s2m_{0}_{1}_{2}'.format(key, slave.name, p.name), p.width)) self.verilog_writer.add(ModulePort('wb_clk_i', 'input')) self.verilog_writer.add(ModulePort('wb_rst_i', 'input')) template_ports = [Port('wb_clk_i', 'wb_clk'), Port('wb_rst_i', 'wb_rst')] template_parameters = [] for master in self.masters.values(): self._gen_mux(master) master_template_ports = self._gen_wishbone_master_port(master) template_ports.extend(master_template_ports) for slave in self.slaves.values(): if len(slave.masters) > 1: self._gen_arbiter(slave) if int(slave.datawidth) < 32: self._gen_resize(slave) slave_template_ports = self._gen_wishbone_port(slave) template_ports.extend(slave_template_ports) self.template_writer.add(Instance(self.name, self.name+'0', template_parameters, template_ports)) self.verilog_writer.write(file) self.template_writer.write(file+'h') core_file = self.vlnv.split(':')[2]+'.core' vlnv = self.vlnv with open(core_file, 'w') as f: f.write('CAPI=2:\n') files = [{file : {'file_type' : 'verilogSource'}}, {file+'h' : {'is_include_file' : True, 'file_type' : 'verilogSource'}} ] coredata = {'name' : vlnv, 'targets' : {'default' : {}}, } coredata['filesets'] = {'rtl' : {'files' : files}} coredata['targets']['default']['filesets'] = ['rtl'] f.write(yaml.dump(coredata))