From f0dba208db40434016d8b5d24b2b57b8f24a4d16 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Fri, 24 May 2019 10:57:58 +0200 Subject: [PATCH 01/11] Add FuseSoC core file --- axi_node.core | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 axi_node.core diff --git a/axi_node.core b/axi_node.core new file mode 100644 index 0000000..830b62f --- /dev/null +++ b/axi_node.core @@ -0,0 +1,46 @@ +CAPI=2: + +name : pulp-platform.org::axi_node:1.1.1 + +filesets: + core: + files: + - src/apb_regs_top.sv + - src/axi_address_decoder_AR.sv + - src/axi_address_decoder_AW.sv + - src/axi_address_decoder_BR.sv + - src/axi_address_decoder_BW.sv + - src/axi_address_decoder_DW.sv + - src/axi_AR_allocator.sv + - src/axi_AW_allocator.sv + - src/axi_BR_allocator.sv + - src/axi_BW_allocator.sv + - src/axi_DW_allocator.sv + - src/axi_multiplexer.sv + - src/axi_node_arbiter.sv + - src/axi_node.sv + - src/axi_regs_top.sv + - src/axi_request_block.sv + - src/axi_response_block.sv + file_type : systemVerilogSource + depend : + - ">=pulp-platform.org::common_cells:1.7.5" + #Required since axi_B(R/W)_allocator.sv uses axi_pkg::RESP_DECERR + - ">=pulp-platform.org::axi:0.4.5" + + interface: + files: + - src/axi_node_intf_wrap.sv + - src/axi_node_wrap_with_slices.sv + file_type : systemVerilogSource + +targets: + default: + filesets : [core, interface] + + lint: + default_tool : verilator + filesets : [core] + tools: + verilator: {mode : lint-only} + toplevel: axi_node From 2004f424b43798fff40b61a53d9bd2a71ee6637e Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Fri, 24 May 2019 11:21:51 +0200 Subject: [PATCH 02/11] Add FuseSoC generator for AXI interconnect --- axi_intercon_gen.py | 424 ++++++++++++++++++++++++++++++++++++++++++++ axi_node.core | 47 +++++ verilogwriter.py | 103 +++++++++++ 3 files changed, 574 insertions(+) create mode 100644 axi_intercon_gen.py create mode 100644 verilogwriter.py diff --git a/axi_intercon_gen.py b/axi_intercon_gen.py new file mode 100644 index 0000000..313824b --- /dev/null +++ b/axi_intercon_gen.py @@ -0,0 +1,424 @@ +#!/usr/bin/env python +import sys +from collections import OrderedDict, defaultdict +import yaml + +from verilogwriter import Signal, Wire, Instance, ModulePort, Port, VerilogWriter + +def axi_signals(id_width, addr_width, user_width, data_width): + signals = [ + ("awid" , False, id_width), + ("awaddr" , False, addr_width ), + ("awlen" , False, 8 ), + ("awsize" , False, 3 ), + ("awburst" , False, 2 ), + ("awlock" , False, 0 ), + ("awcache" , False, 4 ), + ("awprot" , False, 3 ), + ("awregion", False, 4), + ] + if user_width: + signals.append(("awuser" , False, user_width)) + signals += [ + ("awqos" , False, 4), + ("awvalid" , False, 0), + ("awready" , True , 0), + + ("arid" , False, id_width), + ("araddr" , False, addr_width), + ("arlen" , False, 8), + ("arsize" , False, 3), + ("arburst" , False, 2), + ("arlock" , False, 0), + ("arcache" , False, 4), + ("arprot" , False, 3), + ("arregion", False, 4), + ] + if user_width: + signals.append(("aruser" , False, user_width)) + signals += [ + ("arqos" , False, 4), + ("arvalid" , False, 0), + ("arready" , True , 0), + + ("wdata" , False, data_width), + ("wstrb" , False, data_width//8), + ("wlast" , False, 0), + ] + if user_width: + signals.append(("wuser" , False, user_width)) + signals += [ + ("wvalid", False, 0), + ("wready", True , 0), + + ("bid" , True , id_width), + ("bresp" , True , 2), + ("bvalid", True , 0), + ] + if user_width: + signals.append(("buser" , True, user_width)) + signals += [ + ("bready", False, 0), + + ("rid" , True , id_width), + ("rdata" , True , data_width), + ("rresp" , True , 2), + ("rlast" , True , 0), + ] + if user_width: + signals.append(("ruser" , True, user_width)) + signals += [ + ("rvalid", True , 0), + ("rready", False, 0), + ] + return signals + +class AxiBus(object): + def __init__(self, name, id_width, addr_width, user_width, data_width): + self.name = name + self.signals = [ + ("awid" , False, id_width), + ("awaddr" , False, addr_width ), + ("awlen" , False, 8 ), + ("awsize" , False, 3 ), + ("awburst" , False, 2 ), + ("awlock" , False, 0 ), + ("awcache" , False, 4 ), + ("awprot" , False, 3 ), + ("awregion", False, 4), + ] + if user_width: + self.signals.append(("awuser" , False, user_width)) + self.signals += [ + ("awqos" , False, 4), + ("awvalid" , False, 0), + ("awready" , True , 0), + + ("arid" , False, id_width), + ("araddr" , False, addr_width), + ("arlen" , False, 8), + ("arsize" , False, 3), + ("arburst" , False, 2), + ("arlock" , False, 0), + ("arcache" , False, 4), + ("arprot" , False, 3), + ("arregion", False, 4), + ] + if user_width: + self.signals.append(("aruser" , False, user_width)) + self.signals += [ + ("arqos" , False, 4), + ("arvalid" , False, 0), + ("arready" , True , 0), + + ("wdata" , False, data_width), + ("wstrb" , False, data_width//8), + ("wlast" , False, 0), + ] + if user_width: + self.signals.append(("wuser" , False, user_width)) + self.signals += [ + ("wvalid", False, 0), + ("wready", True , 0), + + ("bid" , True , id_width), + ("bresp" , True , 2), + ("bvalid", True , 0), + ] + if user_width: + self.signals.append(("buser" , True, user_width)) + self.signals += [ + ("bready", False, 0), + + ("rid" , True , id_width), + ("rdata" , True , data_width), + ("rresp" , True , 2), + ("rlast" , True , 0), + ] + if user_width: + self.signals.append(("ruser" , True, user_width)) + self.signals += [ + ("rvalid", True , 0), + ("rready", False, 0), + ] + + def assigns(self, masters, slaves, addr_width): + raw = '\n' + i = 0 + for m in masters: + for s in self.signals: + if s[1]: + raw += " assign o_{}_{} = slave_{}[{}];\n".format(m.name, s[0], s[0], i) + else: + raw += " assign slave_{}[{}] = i_{}_{};\n".format(s[0], i, m.name, s[0]) + raw += " assign connectivity_map[{}] = {}'b{};\n".format(i, len(slaves), '1'*len(slaves)) + i += 1 + + raw += '\n' + + i = 0 + for m in slaves: + for s in self.signals: + if s[1]: + raw += " assign master_{}[{}] = i_{}_{};\n".format(s[0], i, m.name, s[0]) + else: + raw += " assign o_{}_{} = master_{}[{}];\n".format(m.name, s[0], s[0], i) + raw += " assign start_addr[0][{}] = 32'h{:08x};\n".format(i, m.offset) + raw += " assign end_addr[0][{}] = 32'h{:08x};\n".format(i, m.offset+m.size-1) + i += 1 + raw += " assign valid_rule[0] = {}'b{};\n".format(len(slaves), '1'*len(slaves)) + return raw + + def module_ports(self, is_input): + ports = [] + for s in self.signals: + prefix = 'o' if is_input == s[1] else 'i' + ports.append(ModulePort("{}_{}_{}".format(prefix, self.name, s[0]), + 'output' if is_input == s[1] else 'input', + s[2])) + return ports + + def instance_ports(self, masters, slaves): + ports = [Port('clk' , 'clk'), + Port('rst_n', 'rst_n'), + Port('test_en_i', "1'b0")] + for s in self.signals: + suffix = 'o' if s[1] else 'i' + name = "slave_{}_{}".format(s[0], suffix) + value = "slave_{}".format(s[0]) + ports.append(Port(name, value)) + + for s in self.signals: + suffix = 'i' if s[1] else 'o' + name = "master_{}_{}".format(s[0], suffix) + value = "master_{}".format(s[0]) + ports.append(Port(name, value)) + + value = '{' + ', '.join(["32'h{start:08x}".format(start=s.offset) for s in slaves]) + '}' + ports.append(Port('cfg_START_ADDR_i', 'start_addr'))#value)) + + value = '{' + ', '.join(["32'h{end:08x}".format(end=s.offset+s.size-1) for s in slaves]) + '}' + ports.append(Port('cfg_END_ADDR_i', 'end_addr'))#value)) + ports.append(Port('cfg_valid_rule_i', "valid_rule")) + ports.append(Port('cfg_connectivity_map_i', "connectivity_map")) + return ports + + def template_ports(self, is_input): + ports = [] + for s in self.signals: + port_name = "{}_{}".format(self.name, s[0]) + prefix = 'o' if is_input == s[1] else 'i' + ports.append(Port("{}_{}".format(prefix, port_name), port_name)) + return ports + + def template_wires(self): + wires = [] + for s in self.signals: + wires.append(Wire("{}_{}".format(self.name, s[0]), s[2])) + return wires + +class Master: + def __init__(self, name, d=None): + self.name = name + self.slaves = [] + if d: + self.load_dict(d) + + def load_dict(self, d): + for key, value in d.items(): + if key == 'slaves': + # Handled in file loading, ignore here + continue + else: + raise UnknownPropertyError( + "Unknown property '%s' in master section '%s'" % ( + key, self.name)) + +class Slave: + def __init__(self, name, d=None): + self.name = name + self.masters = [] + self.offset = 0 + self.size = 0 + self.mask = 0 + if d: + self.load_dict(d) + + def load_dict(self, d): + for key, value in d.items(): + if key == 'offset': + self.offset = value + elif key == 'size': + self.size = value + self.mask = ~(self.size-1) & 0xffffffff + else: + raise UnknownPropertyError( + "Unknown property '%s' in slave section '%s'" % ( + key, self.name)) + +class Parameter: + def __init__(self, name, value): + self.name = name + self.value = value + + + +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'] + #files_root = data['files_root'] + self.vlnv = data['vlnv'] + + for k,v in config['masters'].items(): + print("Found master " + k) + self.masters.append(Master(k,v)) + #d[k] = v['slaves'] + for k,v in config['slaves'].items(): + print("Found slave " + k) + self.slaves.append(Slave(k,v)) + + #for master in self.masters: + + #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', 'axi_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 write(self): + #FIXME + addr_width = 32 + data_width = 64 + id_width = 3 + user_width = 1 + file = self.output_file + + template_ports = [Port('clk' , 'clk'), + Port('rst_n', 'rstn')] + template_parameters = [] + + #Module header + self.verilog_writer.add(ModulePort('clk' , 'input')) + self.verilog_writer.add(ModulePort('rst_n', 'input')) + for master in self.masters: + bus = AxiBus(master.name, id_width, addr_width, user_width, data_width) + for port in bus.module_ports(True): + self.verilog_writer.add(port) + for wire in bus.template_wires(): + self.template_writer.add(wire) + template_ports += bus.template_ports(True) + + for slave in self.slaves: + bus = AxiBus(slave.name, id_width+1, addr_width, user_width, data_width) + for port in bus.module_ports(False): + self.verilog_writer.add(port) + for wire in bus.template_wires(): + self.template_writer.add(wire) + template_ports += bus.template_ports(False) + + raw = "" + + nm = len(self.masters) + for s in axi_signals(id_width, addr_width, user_width, data_width): + raw += " wire [{}:0]".format(nm-1) + if s[2]: + raw += "[{}:0]".format(s[2]-1) + raw += " slave_{};\n".format(s[0]) + ns = len(self.slaves) + for s in axi_signals(id_width+1, addr_width, user_width, data_width): + raw += " wire [{}:0]".format(ns-1) + if s[2]: + raw += "[{}:0]".format(s[2]-1) + raw += " master_{};\n".format(s[0]) + + raw += """ + wire [0:0][{ns}:0][{aw}:0] start_addr; + wire [0:0][{ns}:0][{aw}:0] end_addr; + wire [0:0][{ns}:0] valid_rule; + wire [{nm}:0][{ns}:0] connectivity_map; + """.format(nm=nm-1,aw=addr_width-1, ns=ns-1) + + raw += AxiBus("", id_width, addr_width, user_width, data_width).assigns(self.masters, self.slaves, addr_width) + + self.verilog_writer.raw = raw + parameters = [Parameter('AXI_ADDRESS_W', addr_width), + Parameter('AXI_DATA_W' , data_width), + Parameter('N_MASTER_PORT', len(self.slaves)), + Parameter('N_SLAVE_PORT' , len(self.masters)), + Parameter('AXI_ID_IN' , id_width), + Parameter('AXI_USER_W' , user_width), + Parameter('N_REGION' , 1), + ] + ports = AxiBus(name, id_width, addr_width, user_width, data_width).instance_ports(self.masters, self.slaves) + + self.verilog_writer.add(Instance('axi_node', + 'axi_node', + 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)) + +if __name__ == "__main__": + name = "axi_intercon" + g = AxiIntercon(name, sys.argv[1]) + print("="*80) + g.write() + diff --git a/axi_node.core b/axi_node.core index 830b62f..2c6b510 100644 --- a/axi_node.core +++ b/axi_node.core @@ -34,6 +34,53 @@ filesets: - src/axi_node_wrap_with_slices.sv file_type : systemVerilogSource +generators: + axi_intercon_gen: + interpreter: python + command: axi_intercon_gen.py + description: Generate a wrapper around PULP AXI Node interconnect + usage: | + axi_intercon_gen wraps AXI Node by expanding arrays of signals into + human-readable buses. Memory map can be set with generator parameters. + It will also generate a verilog include file containing the wire + definitions and module instantiation which can be `included in the + module where the interconnect wrapper is intended to be used. + + Parameters: + masters: A dictionary where each key names a master interface connecting + to the interconnect and the associated value contains + configuration for that interface. Currently, there exists no + master configuration keys and the values can be set to null + slaves: A dictionary where each key names a slave interface connecting + to the interconnect and the associated value contains + configuration for that interface. The following configuration + keys are defined + + offset (int): Base address for the slave + size (int): Size of the allocated memory map for the slave + + Example usage: + The following config will generate an interconnect wrapper to which two + AXI4 master interfaces (dma and ibus) are connected, and connects + downstream to three AXI4 slaves (rom, gpio, ram) + + soc_intercon: + generator: axi_intercon_gen + parameters: + masters: + dma: + ibus: + slaves: + ram: + offset : 0 + size: 0x10000000 + gpio: + offset: 0x91000000 + size: 0x1000 + rom: + offset : 0xffff0000 + size : 32768 + targets: default: filesets : [core, interface] diff --git a/verilogwriter.py b/verilogwriter.py new file mode 100644 index 0000000..1122c95 --- /dev/null +++ b/verilogwriter.py @@ -0,0 +1,103 @@ +class Signal(object): + def __init__(self, name, width=0, low=0, asc=False, vec=0): + self.name = name + self.width=width + self.low = low + self.asc = asc + + def range(self): + if self.width > 0: + l = self.width+self.low-1 + r = self.low + if self.asc: + return '['+str(r)+':'+str(l)+']' + else: + return '['+str(l)+':'+str(r)+']' + return '' + +class Wire(Signal): + def write(self, width): + return 'wire{range} {name};\n'.format(range=self.range().rjust(width), name=self.name) + +class Port: + def __init__(self, name, value): + self.name = name + self.value = value + +class ModulePort(Signal): + def __init__(self, name, dir, width=0, low=0, asc=False): + super(ModulePort, self).__init__(name, width, low, asc) + self.dir = dir + + def write(self, range_width=0): + return '{dir} wire {range} {name}'.format(dir=self.dir.ljust(6), range=self.range().rjust(range_width), name=self.name) + +class Instance: + def __init__(self, module, name, parameters, ports): + self.module = module + self.name = name + self.parameters = parameters + self.ports = ports + + def write(self): + s = self.module + if self.parameters: + max_len = max([len(p.name) for p in self.parameters]) + s += '\n #(' + s += ',\n '.join(['.' + p.name.ljust(max_len) +' (' + str(p.value) + ')' for p in self.parameters]) + s += ')\n' + s += ' ' + self.name + + if self.ports: + s += '\n (' + max_len = max([len(p.name) for p in self.ports]) + s += ',\n '.join(['.' + p.name.ljust(max_len) +' (' + str(p.value) + ')' for p in self.ports]) + s += ')' + s += ';\n' + return s + +class VerilogWriter: + raw = "" + def __init__(self, name): + self.name = name + self.instances = [] + self.ports = [] + self.wires = [] + + def add(self, obj): + if isinstance(obj, Instance): + self.instances += [obj] + elif isinstance(obj, ModulePort): + self.ports += [obj] + elif isinstance(obj, Wire): + self.wires += [obj] + else: + raise Exception("Invalid type!" + str(obj)) + + def write(self, file=None): + s = ("// THIS FILE IS AUTOGENERATED BY axi_intercon_gen\n" + "// ANY MANUAL CHANGES WILL BE LOST\n") + s += "`default_nettype none\n" + if self.ports: + s += "module {name}\n".format(name=self.name) + max_len = max([len(p.range()) for p in self.ports]) + s += ' (' + s += ',\n '.join([p.write(max_len) for p in self.ports]) + s += ')' + s += ';\n\n' + if self.wires: + max_len = max([len(w.range()) for w in self.wires]) + for w in self.wires: + s += w.write(max_len + 1) + s +='\n' + s += self.raw + for i in self.instances: + s += i.write() + s += '\n' + if self.ports: + s += 'endmodule\n' + if file is None: + return s + else: + f = open(file,'w') + f.write(s) From a07b0fcaa56796c5e51352815e612a0677bdab5b Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Wed, 26 Jun 2019 12:38:11 +0200 Subject: [PATCH 03/11] Support individual id_width in generator --- axi_intercon_gen.py | 338 +++++++++++++++++++------------------------- axi_node.core | 14 +- 2 files changed, 155 insertions(+), 197 deletions(-) diff --git a/axi_intercon_gen.py b/axi_intercon_gen.py index 313824b..b0b952f 100644 --- a/axi_intercon_gen.py +++ b/axi_intercon_gen.py @@ -1,14 +1,21 @@ #!/usr/bin/env python +import math import sys from collections import OrderedDict, defaultdict import yaml from verilogwriter import Signal, Wire, Instance, ModulePort, Port, VerilogWriter -def axi_signals(id_width, addr_width, user_width, data_width): +class Widths: + addr = 0 + user = 0 + data = 0 + max_id = 0 + +def axi_signals(w, id_width): signals = [ ("awid" , False, id_width), - ("awaddr" , False, addr_width ), + ("awaddr" , False, w.addr ), ("awlen" , False, 8 ), ("awsize" , False, 3 ), ("awburst" , False, 2 ), @@ -16,16 +23,13 @@ def axi_signals(id_width, addr_width, user_width, data_width): ("awcache" , False, 4 ), ("awprot" , False, 3 ), ("awregion", False, 4), - ] - if user_width: - signals.append(("awuser" , False, user_width)) - signals += [ + ("awuser" , False, w.user), ("awqos" , False, 4), ("awvalid" , False, 0), ("awready" , True , 0), ("arid" , False, id_width), - ("araddr" , False, addr_width), + ("araddr" , False, w.addr), ("arlen" , False, 8), ("arsize" , False, 3), ("arburst" , False, 2), @@ -33,194 +37,138 @@ def axi_signals(id_width, addr_width, user_width, data_width): ("arcache" , False, 4), ("arprot" , False, 3), ("arregion", False, 4), - ] - if user_width: - signals.append(("aruser" , False, user_width)) - signals += [ + ("aruser" , False, w.user), ("arqos" , False, 4), ("arvalid" , False, 0), ("arready" , True , 0), - ("wdata" , False, data_width), - ("wstrb" , False, data_width//8), + ("wdata" , False, w.data), + ("wstrb" , False, w.data//8), ("wlast" , False, 0), - ] - if user_width: - signals.append(("wuser" , False, user_width)) - signals += [ + ("wuser" , False, w.user), ("wvalid", False, 0), ("wready", True , 0), ("bid" , True , id_width), ("bresp" , True , 2), ("bvalid", True , 0), - ] - if user_width: - signals.append(("buser" , True, user_width)) - signals += [ + ("buser" , True, w.user), ("bready", False, 0), ("rid" , True , id_width), - ("rdata" , True , data_width), + ("rdata" , True , w.data), ("rresp" , True , 2), ("rlast" , True , 0), - ] - if user_width: - signals.append(("ruser" , True, user_width)) - signals += [ + ("ruser" , True, w.user), ("rvalid", True , 0), ("rready", False, 0), ] return signals -class AxiBus(object): - def __init__(self, name, id_width, addr_width, user_width, data_width): - self.name = name - self.signals = [ - ("awid" , False, id_width), - ("awaddr" , False, addr_width ), - ("awlen" , False, 8 ), - ("awsize" , False, 3 ), - ("awburst" , False, 2 ), - ("awlock" , False, 0 ), - ("awcache" , False, 4 ), - ("awprot" , False, 3 ), - ("awregion", False, 4), - ] - if user_width: - self.signals.append(("awuser" , False, user_width)) - self.signals += [ - ("awqos" , False, 4), - ("awvalid" , False, 0), - ("awready" , True , 0), - - ("arid" , False, id_width), - ("araddr" , False, addr_width), - ("arlen" , False, 8), - ("arsize" , False, 3), - ("arburst" , False, 2), - ("arlock" , False, 0), - ("arcache" , False, 4), - ("arprot" , False, 3), - ("arregion", False, 4), - ] - if user_width: - self.signals.append(("aruser" , False, user_width)) - self.signals += [ - ("arqos" , False, 4), - ("arvalid" , False, 0), - ("arready" , True , 0), - - ("wdata" , False, data_width), - ("wstrb" , False, data_width//8), - ("wlast" , False, 0), - ] - if user_width: - self.signals.append(("wuser" , False, user_width)) - self.signals += [ - ("wvalid", False, 0), - ("wready", True , 0), - - ("bid" , True , id_width), - ("bresp" , True , 2), - ("bvalid", True , 0), - ] - if user_width: - self.signals.append(("buser" , True, user_width)) - self.signals += [ - ("bready", False, 0), - - ("rid" , True , id_width), - ("rdata" , True , data_width), - ("rresp" , True , 2), - ("rlast" , True , 0), - ] - if user_width: - self.signals.append(("ruser" , True, user_width)) - self.signals += [ - ("rvalid", True , 0), - ("rready", False, 0), - ] - - def assigns(self, masters, slaves, addr_width): - raw = '\n' - i = 0 - for m in masters: - for s in self.signals: - if s[1]: - raw += " assign o_{}_{} = slave_{}[{}];\n".format(m.name, s[0], s[0], i) - else: - raw += " assign slave_{}[{}] = i_{}_{};\n".format(s[0], i, m.name, s[0]) - raw += " assign connectivity_map[{}] = {}'b{};\n".format(i, len(slaves), '1'*len(slaves)) - i += 1 - - raw += '\n' - - i = 0 - for m in slaves: - for s in self.signals: - if s[1]: - raw += " assign master_{}[{}] = i_{}_{};\n".format(s[0], i, m.name, s[0]) - else: - raw += " assign o_{}_{} = master_{}[{}];\n".format(m.name, s[0], s[0], i) - raw += " assign start_addr[0][{}] = 32'h{:08x};\n".format(i, m.offset) - raw += " assign end_addr[0][{}] = 32'h{:08x};\n".format(i, m.offset+m.size-1) - i += 1 - raw += " assign valid_rule[0] = {}'b{};\n".format(len(slaves), '1'*len(slaves)) - return raw - - def module_ports(self, is_input): - ports = [] - for s in self.signals: - prefix = 'o' if is_input == s[1] else 'i' - ports.append(ModulePort("{}_{}_{}".format(prefix, self.name, s[0]), - 'output' if is_input == s[1] else 'input', - s[2])) - return ports - - def instance_ports(self, masters, slaves): - ports = [Port('clk' , 'clk'), - Port('rst_n', 'rst_n'), - Port('test_en_i', "1'b0")] - for s in self.signals: - suffix = 'o' if s[1] else 'i' - name = "slave_{}_{}".format(s[0], suffix) +def module_ports(w, name, id_width, is_input): + ports = [] + for s in axi_signals(w, id_width): + if s[0].endswith('user') and not w.user: + continue + prefix = 'o' if is_input == s[1] else 'i' + ports.append(ModulePort("{}_{}_{}".format(prefix, name, s[0]), + 'output' if is_input == s[1] else 'input', + s[2])) + return ports + +def assigns(w, max_idw, masters, slaves): + raw = '\n' + i = 0 + for m in masters: + for s in axi_signals(w, m.idw): + if s[0].endswith('user') and not w.user: + continue + if s[1]: + src = "slave_{}[{}]".format(s[0], i) + if s[0] in ['bid', 'rid'] and m.idw < max_idw: + src = src+'[{}:0]'.format(m.idw-1) + raw += " assign o_{}_{} = {};\n".format(m.name, s[0], src) + else: + src = "i_{}_{}".format(m.name, s[0]) + if s[0] in ['arid', 'awid'] and m.idw < max_idw: + src = "{"+ str(max_idw-m.idw)+"'d0,"+src+"}" + raw += " assign slave_{}[{}] = {};\n".format(s[0], i, src) + raw += " assign connectivity_map[{}] = {}'b{};\n".format(i, len(slaves), '1'*len(slaves)) + i += 1 + + raw += '\n' + + i = 0 + for m in slaves: + for s in axi_signals(w, max_idw): + if s[0].endswith('user') and not w.user: + continue + if s[1]: + raw += " assign master_{}[{}] = i_{}_{};\n".format(s[0], i, m.name, s[0]) + else: + raw += " assign o_{}_{} = master_{}[{}];\n".format(m.name, s[0], s[0], i) + raw += " assign start_addr[0][{}] = 32'h{:08x};\n".format(i, m.offset) + raw += " assign end_addr[0][{}] = 32'h{:08x};\n".format(i, m.offset+m.size-1) + i += 1 + raw += " assign valid_rule[0] = {}'b{};\n".format(len(slaves), '1'*len(slaves)) + return raw + +def instance_ports(w, id_width, masters, slaves): + ports = [Port('clk' , 'clk'), + Port('rst_n', 'rst_n'), + Port('test_en_i', "1'b0"), + Port('slave_awatop_i', "{}'d0".format(len(masters)*6)), + Port('master_awatop_o', '')] + for s in axi_signals(w, id_width): + suffix = 'o' if s[1] else 'i' + name = "slave_{}_{}".format(s[0], suffix) + if s[0].endswith('user') and not w.user: + value = "" if s[1] else "{}'d0".format(len(masters)) + else: value = "slave_{}".format(s[0]) - ports.append(Port(name, value)) - - for s in self.signals: - suffix = 'i' if s[1] else 'o' - name = "master_{}_{}".format(s[0], suffix) + ports.append(Port(name, value)) + + for s in axi_signals(w, id_width): + suffix = 'i' if s[1] else 'o' + name = "master_{}_{}".format(s[0], suffix) + if s[0].endswith('user') and not w.user: + value = "{}'d0".format(len(slaves)) if s[1] else "" + else: value = "master_{}".format(s[0]) - ports.append(Port(name, value)) - - value = '{' + ', '.join(["32'h{start:08x}".format(start=s.offset) for s in slaves]) + '}' - ports.append(Port('cfg_START_ADDR_i', 'start_addr'))#value)) - - value = '{' + ', '.join(["32'h{end:08x}".format(end=s.offset+s.size-1) for s in slaves]) + '}' - ports.append(Port('cfg_END_ADDR_i', 'end_addr'))#value)) - ports.append(Port('cfg_valid_rule_i', "valid_rule")) - ports.append(Port('cfg_connectivity_map_i', "connectivity_map")) - return ports - - def template_ports(self, is_input): - ports = [] - for s in self.signals: - port_name = "{}_{}".format(self.name, s[0]) - prefix = 'o' if is_input == s[1] else 'i' - ports.append(Port("{}_{}".format(prefix, port_name), port_name)) - return ports - - def template_wires(self): - wires = [] - for s in self.signals: - wires.append(Wire("{}_{}".format(self.name, s[0]), s[2])) - return wires + ports.append(Port(name, value)) + + value = '{' + ', '.join(["32'h{start:08x}".format(start=s.offset) for s in slaves]) + '}' + ports.append(Port('cfg_START_ADDR_i', 'start_addr'))#value)) + + value = '{' + ', '.join(["32'h{end:08x}".format(end=s.offset+s.size-1) for s in slaves]) + '}' + ports.append(Port('cfg_END_ADDR_i', 'end_addr'))#value)) + ports.append(Port('cfg_valid_rule_i', "valid_rule")) + ports.append(Port('cfg_connectivity_map_i', "connectivity_map")) + return ports + +def template_ports(w, name, id_width, is_input): + ports = [] + for s in axi_signals(w, id_width): + if s[0].endswith('user') and not w.user: + continue + port_name = "{}_{}".format(name, s[0]) + prefix = 'o' if is_input == s[1] else 'i' + ports.append(Port("{}_{}".format(prefix, port_name), port_name)) + return ports + +def template_wires(w, name, id_width): + wires = [] + for s in axi_signals(w, id_width): + if s[0].endswith('user') and not w.user: + continue + wires.append(Wire("{}_{}".format(name, s[0]), s[2])) + return wires class Master: def __init__(self, name, d=None): self.name = name self.slaves = [] + self.idw = 1 if d: self.load_dict(d) @@ -229,6 +177,8 @@ def load_dict(self, d): if key == 'slaves': # Handled in file loading, ignore here continue + if key == 'id_width': + self.idw = value else: raise UnknownPropertyError( "Unknown property '%s' in master section '%s'" % ( @@ -321,46 +271,50 @@ def _dump(self): print(' ' + master.name) def write(self): - #FIXME - addr_width = 32 - data_width = 64 - id_width = 3 - user_width = 1 + w = Widths() + w.addr = 32 + w.data = 64 + w.user = 0 + + max_idw = max([m.idw for m in self.masters]) + max_sidw = max_idw + math.ceil(math.log2(len(self.masters))) file = self.output_file - template_ports = [Port('clk' , 'clk'), - Port('rst_n', 'rstn')] + _template_ports = [Port('clk' , 'clk'), + Port('rst_n', 'rstn')] template_parameters = [] #Module header self.verilog_writer.add(ModulePort('clk' , 'input')) self.verilog_writer.add(ModulePort('rst_n', 'input')) for master in self.masters: - bus = AxiBus(master.name, id_width, addr_width, user_width, data_width) - for port in bus.module_ports(True): + for port in module_ports(w, master.name, master.idw, True): self.verilog_writer.add(port) - for wire in bus.template_wires(): + for wire in template_wires(w, master.name, master.idw): self.template_writer.add(wire) - template_ports += bus.template_ports(True) + _template_ports += template_ports(w, master.name, master.idw, True) for slave in self.slaves: - bus = AxiBus(slave.name, id_width+1, addr_width, user_width, data_width) - for port in bus.module_ports(False): + for port in module_ports(w, slave.name, max_sidw, False): self.verilog_writer.add(port) - for wire in bus.template_wires(): + for wire in template_wires(w, slave.name, max_sidw): self.template_writer.add(wire) - template_ports += bus.template_ports(False) + _template_ports += template_ports(w, slave.name, max_sidw, False) raw = "" nm = len(self.masters) - for s in axi_signals(id_width, addr_width, user_width, data_width): + for s in axi_signals(w, max_idw): + if s[0].endswith('user') and not w.user: + continue raw += " wire [{}:0]".format(nm-1) if s[2]: raw += "[{}:0]".format(s[2]-1) raw += " slave_{};\n".format(s[0]) ns = len(self.slaves) - for s in axi_signals(id_width+1, addr_width, user_width, data_width): + for s in axi_signals(w, max_sidw): + if s[0].endswith('user') and not w.user: + continue raw += " wire [{}:0]".format(ns-1) if s[2]: raw += "[{}:0]".format(s[2]-1) @@ -371,20 +325,20 @@ def write(self): wire [0:0][{ns}:0][{aw}:0] end_addr; wire [0:0][{ns}:0] valid_rule; wire [{nm}:0][{ns}:0] connectivity_map; - """.format(nm=nm-1,aw=addr_width-1, ns=ns-1) + """.format(nm=nm-1,aw=w.addr-1, ns=ns-1) - raw += AxiBus("", id_width, addr_width, user_width, data_width).assigns(self.masters, self.slaves, addr_width) + raw += assigns(w, max_idw, self.masters, self.slaves) self.verilog_writer.raw = raw - parameters = [Parameter('AXI_ADDRESS_W', addr_width), - Parameter('AXI_DATA_W' , data_width), + parameters = [Parameter('AXI_ADDRESS_W', w.addr), + Parameter('AXI_DATA_W' , w.data), Parameter('N_MASTER_PORT', len(self.slaves)), Parameter('N_SLAVE_PORT' , len(self.masters)), - Parameter('AXI_ID_IN' , id_width), - Parameter('AXI_USER_W' , user_width), + Parameter('AXI_ID_IN' , max_idw), + Parameter('AXI_USER_W' , w.user or 1), Parameter('N_REGION' , 1), ] - ports = AxiBus(name, id_width, addr_width, user_width, data_width).instance_ports(self.masters, self.slaves) + ports = instance_ports(w, max_idw, self.masters, self.slaves) self.verilog_writer.add(Instance('axi_node', 'axi_node', @@ -394,7 +348,7 @@ def write(self): self.template_writer.add(Instance(self.name, self.name, template_parameters, - template_ports)) + _template_ports)) self.verilog_writer.write(file) self.template_writer.write(file+'h') diff --git a/axi_node.core b/axi_node.core index 2c6b510..9dba32c 100644 --- a/axi_node.core +++ b/axi_node.core @@ -1,6 +1,6 @@ CAPI=2: -name : pulp-platform.org::axi_node:1.1.1 +name : pulp-platform.org::axi_node:1.1.1-r2 filesets: core: @@ -49,8 +49,10 @@ generators: Parameters: masters: A dictionary where each key names a master interface connecting to the interconnect and the associated value contains - configuration for that interface. Currently, there exists no - master configuration keys and the values can be set to null + configuration for that interface. + + id_width (int): Width of the id signals for the master + slaves: A dictionary where each key names a slave interface connecting to the interconnect and the associated value contains configuration for that interface. The following configuration @@ -61,15 +63,17 @@ generators: Example usage: The following config will generate an interconnect wrapper to which two - AXI4 master interfaces (dma and ibus) are connected, and connects - downstream to three AXI4 slaves (rom, gpio, ram) + AXI4 master interfaces (dma and ibus) with different id widths are + connected, and connects downstream to three AXI4 slaves (rom, gpio, ram) soc_intercon: generator: axi_intercon_gen parameters: masters: dma: + id_width : 1 ibus: + id_width : 2 slaves: ram: offset : 0 From 8ef3aba04dbb7d1a189f982469233ad0c0a8c212 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 23 Jul 2019 15:25:27 +0200 Subject: [PATCH 04/11] Add support for read-only AXI ports --- axi_intercon_gen.py | 49 ++++++++++++++++++++++++++++++++++----------- axi_node.core | 2 +- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/axi_intercon_gen.py b/axi_intercon_gen.py index b0b952f..7e18cd5 100644 --- a/axi_intercon_gen.py +++ b/axi_intercon_gen.py @@ -65,13 +65,19 @@ def axi_signals(w, id_width): ] return signals -def module_ports(w, name, id_width, is_input): +def module_ports(w, intf, id_width, is_input): ports = [] for s in axi_signals(w, id_width): if s[0].endswith('user') and not w.user: continue + if s[0].startswith('aw') and intf.read_only: + continue + if s[0].startswith('w') and intf.read_only: + continue + if s[0].startswith('b') and intf.read_only: + continue prefix = 'o' if is_input == s[1] else 'i' - ports.append(ModulePort("{}_{}_{}".format(prefix, name, s[0]), + ports.append(ModulePort("{}_{}_{}".format(prefix, intf.name, s[0]), 'output' if is_input == s[1] else 'input', s[2])) return ports @@ -84,6 +90,8 @@ def assigns(w, max_idw, masters, slaves): if s[0].endswith('user') and not w.user: continue if s[1]: + if m.read_only and (s[0].startswith('aw') or s[0].startswith('w') or s[0].startswith('b')): + continue src = "slave_{}[{}]".format(s[0], i) if s[0] in ['bid', 'rid'] and m.idw < max_idw: src = src+'[{}:0]'.format(m.idw-1) @@ -92,6 +100,12 @@ def assigns(w, max_idw, masters, slaves): src = "i_{}_{}".format(m.name, s[0]) if s[0] in ['arid', 'awid'] and m.idw < max_idw: src = "{"+ str(max_idw-m.idw)+"'d0,"+src+"}" + if m.read_only and (s[0].startswith('aw') or s[0].startswith('w') or s[0].startswith('b')): + if s[0] in ['awid']: + _w = max_idw + else: + _w = max(1,s[2]) + src = "{}'d0".format(_w) raw += " assign slave_{}[{}] = {};\n".format(s[0], i, src) raw += " assign connectivity_map[{}] = {}'b{};\n".format(i, len(slaves), '1'*len(slaves)) i += 1 @@ -146,22 +160,26 @@ def instance_ports(w, id_width, masters, slaves): ports.append(Port('cfg_connectivity_map_i', "connectivity_map")) return ports -def template_ports(w, name, id_width, is_input): +def template_ports(w, intf, id_width, is_input): ports = [] for s in axi_signals(w, id_width): if s[0].endswith('user') and not w.user: continue - port_name = "{}_{}".format(name, s[0]) + if intf.read_only and (s[0].startswith('aw') or s[0].startswith('w') or s[0].startswith('b')): + continue + port_name = "{}_{}".format(intf.name, s[0]) prefix = 'o' if is_input == s[1] else 'i' ports.append(Port("{}_{}".format(prefix, port_name), port_name)) return ports -def template_wires(w, name, id_width): +def template_wires(w, intf, id_width): wires = [] for s in axi_signals(w, id_width): if s[0].endswith('user') and not w.user: continue - wires.append(Wire("{}_{}".format(name, s[0]), s[2])) + if intf.read_only and (s[0].startswith('aw') or s[0].startswith('w') or s[0].startswith('b')): + continue + wires.append(Wire("{}_{}".format(intf.name, s[0]), s[2])) return wires class Master: @@ -169,6 +187,7 @@ def __init__(self, name, d=None): self.name = name self.slaves = [] self.idw = 1 + self.read_only = False if d: self.load_dict(d) @@ -179,7 +198,10 @@ def load_dict(self, d): continue if key == 'id_width': self.idw = value + elif key == 'read_only': + self.read_only = value else: + print(key) raise UnknownPropertyError( "Unknown property '%s' in master section '%s'" % ( key, self.name)) @@ -191,6 +213,7 @@ def __init__(self, name, d=None): self.offset = 0 self.size = 0 self.mask = 0 + self.read_only = False if d: self.load_dict(d) @@ -201,6 +224,8 @@ def load_dict(self, d): elif key == 'size': self.size = value self.mask = ~(self.size-1) & 0xffffffff + elif key == 'read_only': + self.read_only = value else: raise UnknownPropertyError( "Unknown property '%s' in slave section '%s'" % ( @@ -288,18 +313,18 @@ def write(self): self.verilog_writer.add(ModulePort('clk' , 'input')) self.verilog_writer.add(ModulePort('rst_n', 'input')) for master in self.masters: - for port in module_ports(w, master.name, master.idw, True): + for port in module_ports(w, master, master.idw, True): self.verilog_writer.add(port) - for wire in template_wires(w, master.name, master.idw): + for wire in template_wires(w, master, master.idw): self.template_writer.add(wire) - _template_ports += template_ports(w, master.name, master.idw, True) + _template_ports += template_ports(w, master, master.idw, True) for slave in self.slaves: - for port in module_ports(w, slave.name, max_sidw, False): + for port in module_ports(w, slave, max_sidw, False): self.verilog_writer.add(port) - for wire in template_wires(w, slave.name, max_sidw): + for wire in template_wires(w, slave, max_sidw): self.template_writer.add(wire) - _template_ports += template_ports(w, slave.name, max_sidw, False) + _template_ports += template_ports(w, slave, max_sidw, False) raw = "" diff --git a/axi_node.core b/axi_node.core index 9dba32c..0b439b4 100644 --- a/axi_node.core +++ b/axi_node.core @@ -1,6 +1,6 @@ CAPI=2: -name : pulp-platform.org::axi_node:1.1.1-r2 +name : pulp-platform.org::axi_node:1.1.1-r3 filesets: core: From 9673aac0eb33b76f84d148ce5455e8e15462e0e7 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 5 Sep 2019 15:52:02 +0200 Subject: [PATCH 05/11] Fix Python2 compatibility --- axi_intercon_gen.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/axi_intercon_gen.py b/axi_intercon_gen.py index 7e18cd5..8c2e6e8 100644 --- a/axi_intercon_gen.py +++ b/axi_intercon_gen.py @@ -6,6 +6,10 @@ from verilogwriter import Signal, Wire, Instance, ModulePort, Port, VerilogWriter +if sys.version[0] == '2': + + math.log2 = lambda x : math.log(x, 2) + class Widths: addr = 0 user = 0 @@ -302,7 +306,7 @@ def write(self): w.user = 0 max_idw = max([m.idw for m in self.masters]) - max_sidw = max_idw + math.ceil(math.log2(len(self.masters))) + max_sidw = max_idw + int(math.ceil(math.log2(len(self.masters)))) file = self.output_file _template_ports = [Port('clk' , 'clk'), From fdb9798a846bc2564b1716c42e10c0d2801b9a18 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 5 Sep 2019 15:54:46 +0200 Subject: [PATCH 06/11] Only set default_nettype none when generating modules --- verilogwriter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verilogwriter.py b/verilogwriter.py index 1122c95..10c3406 100644 --- a/verilogwriter.py +++ b/verilogwriter.py @@ -77,8 +77,8 @@ def add(self, obj): def write(self, file=None): s = ("// THIS FILE IS AUTOGENERATED BY axi_intercon_gen\n" "// ANY MANUAL CHANGES WILL BE LOST\n") - s += "`default_nettype none\n" if self.ports: + s += "`default_nettype none\n" s += "module {name}\n".format(name=self.name) max_len = max([len(p.range()) for p in self.ports]) s += ' (' From 9fb32e909edabcbdc6ebdc3d5170ca301ae44ea8 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Fri, 6 Sep 2019 16:02:57 +0200 Subject: [PATCH 07/11] Bump core version --- axi_node.core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axi_node.core b/axi_node.core index 0b439b4..4a47430 100644 --- a/axi_node.core +++ b/axi_node.core @@ -1,6 +1,6 @@ CAPI=2: -name : pulp-platform.org::axi_node:1.1.1-r3 +name : pulp-platform.org::axi_node:1.1.1-r4 filesets: core: From 151e66cbba3ded21978a8374559f1627f6e64ab1 Mon Sep 17 00:00:00 2001 From: operoutka Date: Thu, 5 Mar 2020 14:52:11 +0100 Subject: [PATCH 08/11] Modified axi_node_arbiter so fusesoc can run with VCS --- src/axi_node_arbiter.sv | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/axi_node_arbiter.sv b/src/axi_node_arbiter.sv index 8f72b1c..cf8d86b 100644 --- a/src/axi_node_arbiter.sv +++ b/src/axi_node_arbiter.sv @@ -27,17 +27,14 @@ module axi_node_arbiter #( input logic oup_ready_i ); - typedef struct packed { - logic [AUX_WIDTH-1:0] aux; - logic [ID_WIDTH-1:0] id; - } axi_meta_t; + typedef logic [AUX_WIDTH+ID_WIDTH-1:0] axi_meta_t; axi_meta_t [N_MASTER-1:0] inp_meta; axi_meta_t oup_meta; for (genvar i = 0; i < N_MASTER; i++) begin: gen_inp_meta - assign inp_meta[i].aux = inp_aux_i[i]; - assign inp_meta[i].id = inp_id_i[i]; + assign inp_meta[i][AUX_WIDTH+ID_WIDTH-1:ID_WIDTH] = inp_aux_i[i]; + assign inp_meta[i][ID_WIDTH-1:0] = inp_id_i[i]; end stream_arbiter #( @@ -54,8 +51,8 @@ module axi_node_arbiter #( .oup_ready_i (oup_ready_i) ); - assign oup_id_o = oup_meta.id; - assign oup_aux_o = oup_meta.aux; + assign oup_id_o = oup_meta[ID_WIDTH-1:0]; + assign oup_aux_o = oup_meta[AUX_WIDTH+ID_WIDTH-1:ID_WIDTH]; // pragma translate_off `ifndef VERILATOR From 94d9b4e5da1fa243c91e6275a5567f0323574434 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Fri, 6 Mar 2020 10:12:01 +0100 Subject: [PATCH 09/11] Bump core version --- axi_node.core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axi_node.core b/axi_node.core index 4a47430..118d572 100644 --- a/axi_node.core +++ b/axi_node.core @@ -1,6 +1,6 @@ CAPI=2: -name : pulp-platform.org::axi_node:1.1.1-r4 +name : pulp-platform.org::axi_node:1.1.1-r5 filesets: core: From 721d08c3edfe8c1c539e120681d6924c2e7e4278 Mon Sep 17 00:00:00 2001 From: Dawid Zimonczyk Date: Wed, 1 Apr 2020 14:51:56 +0200 Subject: [PATCH 10/11] fix for incompatible modport connection --- src/axi_node_wrap_with_slices.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/axi_node_wrap_with_slices.sv b/src/axi_node_wrap_with_slices.sv index 4f1c302..6255e6d 100644 --- a/src/axi_node_wrap_with_slices.sv +++ b/src/axi_node_wrap_with_slices.sv @@ -33,8 +33,8 @@ module axi_node_wrap_with_slices #( input logic clk, input logic rst_n, input logic test_en_i, - AXI_BUS.Slave slave [NB_SLAVE-1:0], - AXI_BUS.Master master [NB_MASTER-1:0], + AXI_BUS slave [NB_SLAVE-1:0], + AXI_BUS master [NB_MASTER-1:0], // Memory map input logic [NB_REGION-1:0][NB_MASTER-1:0][AXI_ADDR_WIDTH-1:0] start_addr_i, input logic [NB_REGION-1:0][NB_MASTER-1:0][AXI_ADDR_WIDTH-1:0] end_addr_i, From a6b7410489a2631ab34b81f37b802762a0c7c0c4 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Wed, 8 Apr 2020 15:51:13 +0200 Subject: [PATCH 11/11] Bump core revision --- axi_node.core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/axi_node.core b/axi_node.core index 118d572..4f71327 100644 --- a/axi_node.core +++ b/axi_node.core @@ -1,6 +1,6 @@ CAPI=2: -name : pulp-platform.org::axi_node:1.1.1-r5 +name : pulp-platform.org::axi_node:1.1.1-r6 filesets: core: