Key error when loading overlay

Hi, I’m trying to load my project on KV260, pynq 3.0.1. The top design is not the block design showed below, but a top RTL file, including the block design and my PL part. The top file connects the interface like M_AHB_0 between the BD and PL part.

and i get the following error:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Input In [2], in <cell line: 3>()
      1 from pynq import allocate, Overlay
      2 # import pdb; pdb.set_trace()
----> 3 eva=Overlay("/home/root/jupyter_notebooks/eva/EVA.xsa")

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/overlay.py:319, in Overlay.__init__(self, bitfile_name, dtbo, download, ignore_version, device, gen_cache)
    315 super().__init__(bitfile_name, dtbo, partial=False, device=device)
    317 self._register_drivers()
--> 319 self.device.set_bitfile_name(self.bitfile_name)
    320 self.parser = self.device.parser
    322 self.ip_dict = (
    323     self.gpio_dict
    324 ) = (
    325     self.interrupt_controllers
    326 ) = self.interrupt_pins = self.hierarchy_dict = dict()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/device.py:118, in Device.set_bitfile_name(self, bitfile_name)
    116 def set_bitfile_name(self, bitfile_name: str) -> None:
    117     self.bitfile_name = bitfile_name
--> 118     self.parser = self.get_bitfile_metadata(self.bitfile_name)
    119     self.mem_dict = self.parser.mem_dict
    120     self.ip_dict = self.parser.ip_dict

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/embedded_device.py:690, in EmbeddedDevice.get_bitfile_metadata(self, bitfile_name, partial)
    689 def get_bitfile_metadata(self, bitfile_name:str, partial:bool=False):
--> 690     parser = _get_bitstream_handler(bitfile_name).get_parser(partial=partial)
    691     if parser is None:
    692         raise RuntimeError("Unable to find metadata for bitstream")

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/embedded_device.py:268, in BitstreamHandler.get_parser(self, partial)
    266     parser = XclBin(xclbin_data=xclbin_data)
    267 elif is_xsa:
--> 268     parser = RuntimeMetadataParser(Metadata(input=self._filepath))
    269     if xclbin_data is None:
    270         xclbin_data = _create_xclbin(parser.mem_dict)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/metadata.py:41, in Metadata(input)
     39     return HwhFrontend(_hwhfile=input)
     40 elif str(input).endswith(".xsa"):
---> 41     return XsaFrontend(input=input) 
     42 elif str(input).endswith(".json"):
     43     return JsonFrontend(input=input)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/xsa_frontend.py:24, in XsaFrontend(input)
     22 xsa = XsaParser(input)
     23 xsa.load_bdc_metadata()
---> 24 md = HwhFrontend(_hwhfile=xsa.defaultHwhPaths[0])
     25 md.ext["xsa"] = XsaObjectExtension(xsa=xsa)
     26 for b in md.blocks.values():

File <string>:25, in __init__(self, name, type, generic_type, _parent, _children, ref, ext, _timestamp, hierarchy_name, ports, parameters, blocks, modules, busses, _hierarchies, _hwhfile, _element_tree, _root, _logical2physical_portmap, _physical2logical_portmap, _logical2physical_extern_pm, _physical2logical_extern_pm)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:219, in HwhFrontend.__post_init__(self)
    207 """
    208 Performs the parsing of the hwh into the metadata model
    209 * checks to see if the hwhfile is an XML string or a
   (...)
    216 * Performs a connectivity pass
    217 """
    218 if self._hwhfile != "":
--> 219     self.parse()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:240, in HwhFrontend.parse(self)
    237 self._construct_logical2physical_extern_pm()
    238 self._create_external_ports()
--> 240 self.resolve_addressing()
    241 self.connect_signals()
    243 self.refresh()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:605, in HwhFrontend.resolve_addressing(self)
    598 def resolve_addressing(self) -> None:
    599     """
    600     For all the subordinate ports in the design and manager ports
    601     grab all the addressing information
    602     WARNING: This should only be called after all the cores and ports
    603     have been populated.
    604     """
--> 605     self._resolve_subordinate_addressing()
    606     self._populate_subordinate_regmap()
    607     self._resolve_manager_address_maps()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:452, in HwhFrontend._resolve_subordinate_addressing(self)
    450 for i in self._root.iter("MEMRANGE"):
    451     if i.get("MEMTYPE") == "REGISTER" or i.get("MEMTYPE") == "MEMORY":
--> 452         core = self.blocks[i.get("INSTANCE")]
    453         try:
    454             core = self.blocks[i.get("INSTANCE")]

KeyError: 'M_AHB_0'

I’m a beginner in pynq. Does pynq support the way I build the project? I’m wondering whether I should reconstruct my project with a block design including all the PS and PL stuff, and set it as top.

Here’s the hwh file EVA.hwh (240.6 KB) .

Update: I print out some info related to the error:

core = self.blocks[i.get("INSTANCE")]
print(i)
print(i.get("INSTANCE"))
print(self.blocks)
print(i.get("SLAVEBUSINTERFACE"))
print(i.get("BASEVALUE"))

and i get:

<Element 'MEMRANGE' at 0xffff6b8b2890>
M_AHB_0
{'axi_ahblite_bridge_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff93fd7e20>, 'axi_bram_ctrl_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff78690310>, 'proc_sys_reset_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff6b8f0490>, 'smartconnect_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff6b8f0b50>, 'zynq_ultra_ps_e_0': <pynqmetadata.models.ultrascale_proc_sys_core.UltrascaleProcSysCore object at 0xffff6b8f2ec0>}
M_AHB_0
0xA0000000
<Element 'MEMRANGE' at 0xffff6b8b2980>
axi_bram_ctrl_0
{'axi_ahblite_bridge_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff93fd7e20>, 'axi_bram_ctrl_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff78690310>, 'proc_sys_reset_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff6b8f0490>, 'smartconnect_0': <pynqmetadata.models.ip_core.IPCore object at 0xffff6b8f0b50>, 'zynq_ultra_ps_e_0': <pynqmetadata.models.ultrascale_proc_sys_core.UltrascaleProcSysCore object at 0xffff6b8f2ec0>}
S_AXI
0xB0000000

It seems that it’s a bug about the axi ahb-lite bridge, as its INSTANCE and SLAVEBUSINTERFACE are the same. When _resolve_subordinate_addressing processes port S_AXI, no error appears.

After I skip the error with M_AHB_0, I get another error:

AttributeError                            Traceback (most recent call last)
Input In [2], in <cell line: 3>()
      1 from pynq import allocate, Overlay
      2 # import pdb; pdb.set_trace()
----> 3 eva=Overlay("/home/root/jupyter_notebooks/eva/EVA.xsa")

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/overlay.py:319, in Overlay.__init__(self, bitfile_name, dtbo, download, ignore_version, device, gen_cache)
    315 super().__init__(bitfile_name, dtbo, partial=False, device=device)
    317 self._register_drivers()
--> 319 self.device.set_bitfile_name(self.bitfile_name)
    320 self.parser = self.device.parser
    322 self.ip_dict = (
    323     self.gpio_dict
    324 ) = (
    325     self.interrupt_controllers
    326 ) = self.interrupt_pins = self.hierarchy_dict = dict()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/device.py:118, in Device.set_bitfile_name(self, bitfile_name)
    116 def set_bitfile_name(self, bitfile_name: str) -> None:
    117     self.bitfile_name = bitfile_name
--> 118     self.parser = self.get_bitfile_metadata(self.bitfile_name)
    119     self.mem_dict = self.parser.mem_dict
    120     self.ip_dict = self.parser.ip_dict

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/embedded_device.py:690, in EmbeddedDevice.get_bitfile_metadata(self, bitfile_name, partial)
    689 def get_bitfile_metadata(self, bitfile_name:str, partial:bool=False):
--> 690     parser = _get_bitstream_handler(bitfile_name).get_parser(partial=partial)
    691     if parser is None:
    692         raise RuntimeError("Unable to find metadata for bitstream")

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/embedded_device.py:268, in BitstreamHandler.get_parser(self, partial)
    266     parser = XclBin(xclbin_data=xclbin_data)
    267 elif is_xsa:
--> 268     parser = RuntimeMetadataParser(Metadata(input=self._filepath))
    269     if xclbin_data is None:
    270         xclbin_data = _create_xclbin(parser.mem_dict)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/metadata/runtime_metadata_parser.py:57, in RuntimeMetadataParser.__init__(self, md)
     54 self.family_ps = self.ps.ps_name
     56 self.interrupt_controllers_view = InterruptControllersView(self.md)
---> 57 self.interrupt_controllers = copy.deepcopy(self.interrupt_controllers_view.view)
     59 self.interrupt_pins_view = InterruptPinsView(self.md, self.interrupt_controllers)
     60 self.interrupt_pins = copy.deepcopy(self.interrupt_pins_view.view)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/metadata/interrupt_controllers_view.py:86, in InterruptControllersView.view(self)
     84 controller_list = []
     85 for ps_irq in ps_irq_signals.values():
---> 86     controller_list = controller_list + self._walk_for_irq_controllers(ps_irq)
     88 for controller in controller_list:
     89     repr_dict[controller.name] = {}

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/metadata/interrupt_controllers_view.py:55, in InterruptControllersView._walk_for_irq_controllers(self, sig)
     52     idx = self._base_idx
     54 for dst in sig._connections.values():
---> 55     if dst.parent().parent().vlnv.name == "axi_intc":
     56         dst.parent().parent().ext[
     57             "interrupt_controller_index"
     58         ] = InterruptControllerIndex(index=idx)
     59         self._base_idx = self._base_idx + 1

AttributeError: 'HwhFrontend' object has no attribute 'vlnv'

Should I use AXI interrupt controller instead of direct irq?

2 Likes

Hi @hazhuzhu,

Welcome to the PYNQ community.

Does pynq support the way I build the project?

No, it does not.

I’m wondering whether I should reconstruct my project with a block design including all the PS and PL stuff, and set it as top.

Yes, PYNQ only supports the PS from a block design on the top module.

Mario

1 Like

Thank you for your advice! I reconstruct my project like this:

I package my PL part as an IP “eva_pl”. And in order to assign the address for AHB, when packaging I pack my AHB interface and create an address block for it. So I can assign addresses in BD.

But I get the following error when loading overlay:

---------------------------------------------------------------------------
UnexpectedPortTypeError                   Traceback (most recent call last)
Input In [3], in <cell line: 3>()
      1 # from pynq import allocate, Overlay
      2 # import pdb; pdb.set_trace()
----> 3 eva=Overlay("/home/root/jupyter_notebooks/eva/EVA.xsa")

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/overlay.py:319, in Overlay.__init__(self, bitfile_name, dtbo, download, ignore_version, device, gen_cache)
    315 super().__init__(bitfile_name, dtbo, partial=False, device=device)
    317 self._register_drivers()
--> 319 self.device.set_bitfile_name(self.bitfile_name)
    320 self.parser = self.device.parser
    322 self.ip_dict = (
    323     self.gpio_dict
    324 ) = (
    325     self.interrupt_controllers
    326 ) = self.interrupt_pins = self.hierarchy_dict = dict()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/device.py:118, in Device.set_bitfile_name(self, bitfile_name)
    116 def set_bitfile_name(self, bitfile_name: str) -> None:
    117     self.bitfile_name = bitfile_name
--> 118     self.parser = self.get_bitfile_metadata(self.bitfile_name)
    119     self.mem_dict = self.parser.mem_dict
    120     self.ip_dict = self.parser.ip_dict

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/embedded_device.py:690, in EmbeddedDevice.get_bitfile_metadata(self, bitfile_name, partial)
    689 def get_bitfile_metadata(self, bitfile_name:str, partial:bool=False):
--> 690     parser = _get_bitstream_handler(bitfile_name).get_parser(partial=partial)
    691     if parser is None:
    692         raise RuntimeError("Unable to find metadata for bitstream")

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl_server/embedded_device.py:268, in BitstreamHandler.get_parser(self, partial)
    266     parser = XclBin(xclbin_data=xclbin_data)
    267 elif is_xsa:
--> 268     parser = RuntimeMetadataParser(Metadata(input=self._filepath))
    269     if xclbin_data is None:
    270         xclbin_data = _create_xclbin(parser.mem_dict)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/metadata.py:41, in Metadata(input)
     39     return HwhFrontend(_hwhfile=input)
     40 elif str(input).endswith(".xsa"):
---> 41     return XsaFrontend(input=input) 
     42 elif str(input).endswith(".json"):
     43     return JsonFrontend(input=input)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/xsa_frontend.py:24, in XsaFrontend(input)
     22 xsa = XsaParser(input)
     23 xsa.load_bdc_metadata()
---> 24 md = HwhFrontend(_hwhfile=xsa.defaultHwhPaths[0])
     25 md.ext["xsa"] = XsaObjectExtension(xsa=xsa)
     26 for b in md.blocks.values():

File <string>:25, in __init__(self, name, type, generic_type, _parent, _children, ref, ext, _timestamp, hierarchy_name, ports, parameters, blocks, modules, busses, _hierarchies, _hwhfile, _element_tree, _root, _logical2physical_portmap, _physical2logical_portmap, _logical2physical_extern_pm, _physical2logical_extern_pm)

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:219, in HwhFrontend.__post_init__(self)
    207 """
    208 Performs the parsing of the hwh into the metadata model
    209 * checks to see if the hwhfile is an XML string or a
   (...)
    216 * Performs a connectivity pass
    217 """
    218 if self._hwhfile != "":
--> 219     self.parse()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:240, in HwhFrontend.parse(self)
    237 self._construct_logical2physical_extern_pm()
    238 self._create_external_ports()
--> 240 self.resolve_addressing()
    241 self.connect_signals()
    243 self.refresh()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:611, in HwhFrontend.resolve_addressing(self)
    604 def resolve_addressing(self) -> None:
    605     """
    606     For all the subordinate ports in the design and manager ports
    607     grab all the addressing information
    608     WARNING: This should only be called after all the cores and ports
    609     have been populated.
    610     """
--> 611     self._resolve_subordinate_addressing()
    612     self._populate_subordinate_regmap()
    613     self._resolve_manager_address_maps()

File /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynqmetadata/frontends/hwh_frontend.py:473, in HwhFrontend._resolve_subordinate_addressing(self)
    471     port.range = (int(i.get("HIGHVALUE"), 16) - port.baseaddr) + 1
    472 else:
--> 473     raise UnexpectedPortTypeError(
    474         f"Expected {port.ref} to be SubordinatePort when assigning base address"
    475     )

UnexpectedPortTypeError: Expected EVA:eva_pl_0[block]:S_AHB[port] to be SubordinatePort when assigning base address

But if I don’t create the address block for S_AHB, it will show incomplete path in BD address editor. What is the right way to control AHB BUS in pynq?

If you don’t mind I’d like to ask another question about the bram crontroller. The bram in “eva_pl” is 512-bit width, but the AXI_HPM_FPD is 128bit width at most, so I use a smartconnect to convert it. Can I use these simple codes to write and read the first row in my bram?

bram=overlay.axi_bram_ctrl_0
for i in range(16):
    bram.write(i*4, data[i])
for i in range(16):
    result[i]=bram.read(i*4)
    print(result[i])
1 Like

Hi @hazhuzhu,

Would you mind trying to upgrade your version of Pynq-Metadata to see if it solves the issue. Can you run the following on your board:

python3 -m pip uninstall pynqmetadata
python3 -m pip cache purge
python3 -m pip install pynqmetadata

You might need to reset your board after doing the upgrade just to be sure.

Let me know how you get on!

Thanks,
Shane

1 Like

Hi all,

So apparently it doesn’t matter if the block design wrapper that contains the ZynqPS is actually instantiated in another layer of RTL. What matters is that the ZynqPS IP should be instantiated in the top-level of the BD, i.e not within hierarchical level created inside the BD.

Thanks,
Shant

1 Like

Another one is the AXI interrupt controller IP, it should also be instantiated in the top-level of the BD, i.e not within a hierarchical level created inside the BD.

Thanks,
Shant

1 Like