We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
XGMII monitor crashes with AttributeError
`self._pkt` is initialized to `b""` (immutable), but we are using `.append()` to add payload data to it. This won't work. Maybe instead use a `bytearray()`?

_Originally posted by @LeChuck42 in https://github.com/cocotb/cocotb/pull/1545#issuecomment-635394899_

These lines exemplify the issue:

https://github.com/cocotb/cocotb/blob/924f35a3b7d39543118b7bfaed77dd4808e6612b/cocotb/monitors/xgmii.py#L107-L121

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cocotb/monitors/xgmii.py`
Content:
```
1 # Copyright (c) 2013 Potential Ventures Ltd
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are met:
6 #     * Redistributions of source code must retain the above copyright
7 #       notice, this list of conditions and the following disclaimer.
8 #     * Redistributions in binary form must reproduce the above copyright
9 #       notice, this list of conditions and the following disclaimer in the
10 #       documentation and/or other materials provided with the distribution.
11 #     * Neither the name of Potential Ventures Ltd nor the names of its
12 #       contributors may be used to endorse or promote products derived from this
13 #       software without specific prior written permission.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY
19 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 """Monitor for XGMII (10 Gigabit Media Independent Interface)."""
27 
28 # By default cast to scapy packets, otherwise we pass the string of bytes
29 try:
30     from scapy.all import Ether
31     _have_scapy = True
32 except ImportError:
33     _have_scapy = False
34 
35 import struct
36 import zlib
37 
38 import cocotb
39 from cocotb.utils import hexdump
40 from cocotb.monitors import Monitor
41 from cocotb.triggers import RisingEdge
42 
43 _XGMII_IDLE      = 0x07  # noqa
44 _XGMII_START     = 0xFB  # noqa
45 _XGMII_TERMINATE = 0xFD  # noqa
46 
47 _PREAMBLE_SFD = b"\x55\x55\x55\x55\x55\x55\xD5"
48 
49 
50 class XGMII(Monitor):
51     """XGMII (10 Gigabit Media Independent Interface) Monitor.
52 
53     Assumes a single vector, either 4 or 8 bytes plus control bit for each byte.
54 
55     If interleaved is ``True`` then the control bits are adjacent to the bytes.
56 
57     .. versionchanged:: 1.4.0
58         This now emits packets of type :class:`bytes` rather than :class:`str`,
59         which matches the behavior of :class:`cocotb.drivers.xgmii.XGMII`.
60     """
61 
62     def __init__(self, signal, clock, interleaved=True, callback=None,
63                  event=None):
64         """Args:
65             signal (SimHandle): The XGMII data bus.
66             clock (SimHandle): The associated clock (assumed to be
67                 driven by another coroutine).
68             interleaved (bool, optional): Whether control bits are interleaved
69                 with the data bytes or not.
70 
71         If interleaved the bus is
72             byte0, byte0_control, byte1, byte1_control, ...
73 
74         Otherwise expect
75             byte0, byte1, ..., byte0_control, byte1_control, ...
76         """
77         self.log = signal._log
78         self.clock = clock
79         self.signal = signal
80         self.bytes = len(self.signal) // 9
81         self.interleaved = interleaved
82         Monitor.__init__(self, callback=callback, event=event)
83 
84     def _get_bytes(self):
85         """Take a value and extract the individual bytes and control bits.
86 
87         Returns a tuple of lists.
88         """
89         value = self.signal.value.integer
90         bytes = []
91         ctrls = []
92         byte_shift = 8
93         ctrl_base = 8 * self.bytes
94         ctrl_inc = 1
95         if self.interleaved:
96             byte_shift += 1
97             ctrl_base = 8
98             ctrl_inc = 9
99 
100         for i in range(self.bytes):
101             bytes.append((value >> (i * byte_shift)) & 0xff)
102             ctrls.append(bool(value & (1 << ctrl_base)))
103             ctrl_base += ctrl_inc
104 
105         return ctrls, bytes
106 
107     def _add_payload(self, ctrl, bytes):
108         """Take the payload and return true if more to come"""
109         for index, byte in enumerate(bytes):
110             if ctrl[index]:
111                 if byte != _XGMII_TERMINATE:
112                     self.log.error("Got control character in XGMII payload")
113                     self.log.info("data = :" +
114                                   " ".join(["%02X" % b for b in bytes]))
115                     self.log.info("ctrl = :" +
116                                   " ".join(["%s" % str(c) for c in ctrl]))
117                     self._pkt = b""
118                 return False
119 
120             self._pkt.append(byte)
121         return True
122 
123     @cocotb.coroutine
124     def _monitor_recv(self):
125         clk = RisingEdge(self.clock)
126         self._pkt = b""
127 
128         while True:
129             yield clk
130             ctrl, bytes = self._get_bytes()
131 
132             if ctrl[0] and bytes[0] == _XGMII_START:
133 
134                 ctrl, bytes = ctrl[1:], bytes[1:]
135 
136                 while self._add_payload(ctrl, bytes):
137                     yield clk
138                     ctrl, bytes = self._get_bytes()
139 
140             elif self.bytes == 8 :
141                 if ctrl[4] and bytes[4] == _XGMII_START:
142 
143                     ctrl, bytes = ctrl[5:], bytes[5:]
144 
145                     while self._add_payload(ctrl, bytes):
146                         yield clk
147                         ctrl, bytes = self._get_bytes()
148 
149             if self._pkt:
150 
151                 self.log.debug("Received:\n%s" % (hexdump(self._pkt)))
152 
153                 if len(self._pkt) < 64 + 7:
154                     self.log.error("Received a runt frame!")
155                 if len(self._pkt) < 12:
156                     self.log.error("No data to extract")
157                     self._pkt = b""
158                     continue
159 
160                 preamble_sfd = self._pkt[0:7]
161                 crc32 = self._pkt[-4:]
162                 payload = self._pkt[7:-4]
163 
164                 if preamble_sfd != _PREAMBLE_SFD:
165                     self.log.error("Got a frame with unknown preamble/SFD")
166                     self.log.error(hexdump(preamble_sfd))
167                     self._pkt = b""
168                     continue
169 
170                 expected_crc = struct.pack("<I",
171                                            (zlib.crc32(payload) & 0xFFFFFFFF))
172 
173                 if crc32 != expected_crc:
174                     self.log.error("Incorrect CRC on received packet")
175                     self.log.info("Expected: %s" % (hexdump(expected_crc)))
176                     self.log.info("Received: %s" % (hexdump(crc32)))
177 
178                 # Use scapy to decode the packet
179                 if _have_scapy:
180                     p = Ether(payload)
181                     self.log.debug("Received decoded packet:\n%s" % p.show2())
182                 else:
183                     p = payload
184 
185                 self._recv(p)
186                 self._pkt = b""
187
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cocotb/monitors/xgmii.py b/cocotb/monitors/xgmii.py
--- a/cocotb/monitors/xgmii.py
+++ b/cocotb/monitors/xgmii.py
@@ -114,7 +114,7 @@
                                   " ".join(["%02X" % b for b in bytes]))
                     self.log.info("ctrl = :" +
                                   " ".join(["%s" % str(c) for c in ctrl]))
-                    self._pkt = b""
+                    self._pkt = bytearray()
                 return False
 
             self._pkt.append(byte)
@@ -123,7 +123,7 @@
     @cocotb.coroutine
     def _monitor_recv(self):
         clk = RisingEdge(self.clock)
-        self._pkt = b""
+        self._pkt = bytearray()
 
         while True:
             yield clk
@@ -154,7 +154,7 @@
                     self.log.error("Received a runt frame!")
                 if len(self._pkt) < 12:
                     self.log.error("No data to extract")
-                    self._pkt = b""
+                    self._pkt = bytearray()
                     continue
 
                 preamble_sfd = self._pkt[0:7]
@@ -164,7 +164,7 @@
                 if preamble_sfd != _PREAMBLE_SFD:
                     self.log.error("Got a frame with unknown preamble/SFD")
                     self.log.error(hexdump(preamble_sfd))
-                    self._pkt = b""
+                    self._pkt = bytearray()
                     continue
 
                 expected_crc = struct.pack("<I",
@@ -183,4 +183,4 @@
                     p = payload
 
                 self._recv(p)
-                self._pkt = b""
+                self._pkt = bytearray()

{"golden_diff": "diff --git a/cocotb/monitors/xgmii.py b/cocotb/monitors/xgmii.py\n--- a/cocotb/monitors/xgmii.py\n+++ b/cocotb/monitors/xgmii.py\n@@ -114,7 +114,7 @@\n                                   \" \".join([\"%02X\" % b for b in bytes]))\n                     self.log.info(\"ctrl = :\" +\n                                   \" \".join([\"%s\" % str(c) for c in ctrl]))\n-                    self._pkt = b\"\"\n+                    self._pkt = bytearray()\n                 return False\n \n             self._pkt.append(byte)\n@@ -123,7 +123,7 @@\n     @cocotb.coroutine\n     def _monitor_recv(self):\n         clk = RisingEdge(self.clock)\n-        self._pkt = b\"\"\n+        self._pkt = bytearray()\n \n         while True:\n             yield clk\n@@ -154,7 +154,7 @@\n                     self.log.error(\"Received a runt frame!\")\n                 if len(self._pkt) < 12:\n                     self.log.error(\"No data to extract\")\n-                    self._pkt = b\"\"\n+                    self._pkt = bytearray()\n                     continue\n \n                 preamble_sfd = self._pkt[0:7]\n@@ -164,7 +164,7 @@\n                 if preamble_sfd != _PREAMBLE_SFD:\n                     self.log.error(\"Got a frame with unknown preamble/SFD\")\n                     self.log.error(hexdump(preamble_sfd))\n-                    self._pkt = b\"\"\n+                    self._pkt = bytearray()\n                     continue\n \n                 expected_crc = struct.pack(\"<I\",\n@@ -183,4 +183,4 @@\n                     p = payload\n \n                 self._recv(p)\n-                self._pkt = b\"\"\n+                self._pkt = bytearray()\n", "issue": "XGMII monitor crashes with AttributeError\n`self._pkt` is initialized to `b\"\"` (immutable), but we are using `.append()` to add payload data to it. This won't work. Maybe instead use a `bytearray()`?\r\n\r\n_Originally posted by @LeChuck42 in https://github.com/cocotb/cocotb/pull/1545#issuecomment-635394899_\r\n\r\nThese lines exemplify the issue:\r\n\r\nhttps://github.com/cocotb/cocotb/blob/924f35a3b7d39543118b7bfaed77dd4808e6612b/cocotb/monitors/xgmii.py#L107-L121\n", "before_files": [{"content": "# Copyright (c) 2013 Potential Ventures Ltd\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#     * Redistributions of source code must retain the above copyright\n#       notice, this list of conditions and the following disclaimer.\n#     * Redistributions in binary form must reproduce the above copyright\n#       notice, this list of conditions and the following disclaimer in the\n#       documentation and/or other materials provided with the distribution.\n#     * Neither the name of Potential Ventures Ltd nor the names of its\n#       contributors may be used to endorse or promote products derived from this\n#       software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY\n# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\"\"\"Monitor for XGMII (10 Gigabit Media Independent Interface).\"\"\"\n\n# By default cast to scapy packets, otherwise we pass the string of bytes\ntry:\n    from scapy.all import Ether\n    _have_scapy = True\nexcept ImportError:\n    _have_scapy = False\n\nimport struct\nimport zlib\n\nimport cocotb\nfrom cocotb.utils import hexdump\nfrom cocotb.monitors import Monitor\nfrom cocotb.triggers import RisingEdge\n\n_XGMII_IDLE      = 0x07  # noqa\n_XGMII_START     = 0xFB  # noqa\n_XGMII_TERMINATE = 0xFD  # noqa\n\n_PREAMBLE_SFD = b\"\\x55\\x55\\x55\\x55\\x55\\x55\\xD5\"\n\n\nclass XGMII(Monitor):\n    \"\"\"XGMII (10 Gigabit Media Independent Interface) Monitor.\n\n    Assumes a single vector, either 4 or 8 bytes plus control bit for each byte.\n\n    If interleaved is ``True`` then the control bits are adjacent to the bytes.\n\n    .. versionchanged:: 1.4.0\n        This now emits packets of type :class:`bytes` rather than :class:`str`,\n        which matches the behavior of :class:`cocotb.drivers.xgmii.XGMII`.\n    \"\"\"\n\n    def __init__(self, signal, clock, interleaved=True, callback=None,\n                 event=None):\n        \"\"\"Args:\n            signal (SimHandle): The XGMII data bus.\n            clock (SimHandle): The associated clock (assumed to be\n                driven by another coroutine).\n            interleaved (bool, optional): Whether control bits are interleaved\n                with the data bytes or not.\n\n        If interleaved the bus is\n            byte0, byte0_control, byte1, byte1_control, ...\n\n        Otherwise expect\n            byte0, byte1, ..., byte0_control, byte1_control, ...\n        \"\"\"\n        self.log = signal._log\n        self.clock = clock\n        self.signal = signal\n        self.bytes = len(self.signal) // 9\n        self.interleaved = interleaved\n        Monitor.__init__(self, callback=callback, event=event)\n\n    def _get_bytes(self):\n        \"\"\"Take a value and extract the individual bytes and control bits.\n\n        Returns a tuple of lists.\n        \"\"\"\n        value = self.signal.value.integer\n        bytes = []\n        ctrls = []\n        byte_shift = 8\n        ctrl_base = 8 * self.bytes\n        ctrl_inc = 1\n        if self.interleaved:\n            byte_shift += 1\n            ctrl_base = 8\n            ctrl_inc = 9\n\n        for i in range(self.bytes):\n            bytes.append((value >> (i * byte_shift)) & 0xff)\n            ctrls.append(bool(value & (1 << ctrl_base)))\n            ctrl_base += ctrl_inc\n\n        return ctrls, bytes\n\n    def _add_payload(self, ctrl, bytes):\n        \"\"\"Take the payload and return true if more to come\"\"\"\n        for index, byte in enumerate(bytes):\n            if ctrl[index]:\n                if byte != _XGMII_TERMINATE:\n                    self.log.error(\"Got control character in XGMII payload\")\n                    self.log.info(\"data = :\" +\n                                  \" \".join([\"%02X\" % b for b in bytes]))\n                    self.log.info(\"ctrl = :\" +\n                                  \" \".join([\"%s\" % str(c) for c in ctrl]))\n                    self._pkt = b\"\"\n                return False\n\n            self._pkt.append(byte)\n        return True\n\n    @cocotb.coroutine\n    def _monitor_recv(self):\n        clk = RisingEdge(self.clock)\n        self._pkt = b\"\"\n\n        while True:\n            yield clk\n            ctrl, bytes = self._get_bytes()\n\n            if ctrl[0] and bytes[0] == _XGMII_START:\n\n                ctrl, bytes = ctrl[1:], bytes[1:]\n\n                while self._add_payload(ctrl, bytes):\n                    yield clk\n                    ctrl, bytes = self._get_bytes()\n\n            elif self.bytes == 8 :\n                if ctrl[4] and bytes[4] == _XGMII_START:\n\n                    ctrl, bytes = ctrl[5:], bytes[5:]\n\n                    while self._add_payload(ctrl, bytes):\n                        yield clk\n                        ctrl, bytes = self._get_bytes()\n\n            if self._pkt:\n\n                self.log.debug(\"Received:\\n%s\" % (hexdump(self._pkt)))\n\n                if len(self._pkt) < 64 + 7:\n                    self.log.error(\"Received a runt frame!\")\n                if len(self._pkt) < 12:\n                    self.log.error(\"No data to extract\")\n                    self._pkt = b\"\"\n                    continue\n\n                preamble_sfd = self._pkt[0:7]\n                crc32 = self._pkt[-4:]\n                payload = self._pkt[7:-4]\n\n                if preamble_sfd != _PREAMBLE_SFD:\n                    self.log.error(\"Got a frame with unknown preamble/SFD\")\n                    self.log.error(hexdump(preamble_sfd))\n                    self._pkt = b\"\"\n                    continue\n\n                expected_crc = struct.pack(\"<I\",\n                                           (zlib.crc32(payload) & 0xFFFFFFFF))\n\n                if crc32 != expected_crc:\n                    self.log.error(\"Incorrect CRC on received packet\")\n                    self.log.info(\"Expected: %s\" % (hexdump(expected_crc)))\n                    self.log.info(\"Received: %s\" % (hexdump(crc32)))\n\n                # Use scapy to decode the packet\n                if _have_scapy:\n                    p = Ether(payload)\n                    self.log.debug(\"Received decoded packet:\\n%s\" % p.show2())\n                else:\n                    p = payload\n\n                self._recv(p)\n                self._pkt = b\"\"\n", "path": "cocotb/monitors/xgmii.py"}], "after_files": [{"content": "# Copyright (c) 2013 Potential Ventures Ltd\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are met:\n#     * Redistributions of source code must retain the above copyright\n#       notice, this list of conditions and the following disclaimer.\n#     * Redistributions in binary form must reproduce the above copyright\n#       notice, this list of conditions and the following disclaimer in the\n#       documentation and/or other materials provided with the distribution.\n#     * Neither the name of Potential Ventures Ltd nor the names of its\n#       contributors may be used to endorse or promote products derived from this\n#       software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY\n# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\"\"\"Monitor for XGMII (10 Gigabit Media Independent Interface).\"\"\"\n\n# By default cast to scapy packets, otherwise we pass the string of bytes\ntry:\n    from scapy.all import Ether\n    _have_scapy = True\nexcept ImportError:\n    _have_scapy = False\n\nimport struct\nimport zlib\n\nimport cocotb\nfrom cocotb.utils import hexdump\nfrom cocotb.monitors import Monitor\nfrom cocotb.triggers import RisingEdge\n\n_XGMII_IDLE      = 0x07  # noqa\n_XGMII_START     = 0xFB  # noqa\n_XGMII_TERMINATE = 0xFD  # noqa\n\n_PREAMBLE_SFD = b\"\\x55\\x55\\x55\\x55\\x55\\x55\\xD5\"\n\n\nclass XGMII(Monitor):\n    \"\"\"XGMII (10 Gigabit Media Independent Interface) Monitor.\n\n    Assumes a single vector, either 4 or 8 bytes plus control bit for each byte.\n\n    If interleaved is ``True`` then the control bits are adjacent to the bytes.\n\n    .. versionchanged:: 1.4.0\n        This now emits packets of type :class:`bytes` rather than :class:`str`,\n        which matches the behavior of :class:`cocotb.drivers.xgmii.XGMII`.\n    \"\"\"\n\n    def __init__(self, signal, clock, interleaved=True, callback=None,\n                 event=None):\n        \"\"\"Args:\n            signal (SimHandle): The XGMII data bus.\n            clock (SimHandle): The associated clock (assumed to be\n                driven by another coroutine).\n            interleaved (bool, optional): Whether control bits are interleaved\n                with the data bytes or not.\n\n        If interleaved the bus is\n            byte0, byte0_control, byte1, byte1_control, ...\n\n        Otherwise expect\n            byte0, byte1, ..., byte0_control, byte1_control, ...\n        \"\"\"\n        self.log = signal._log\n        self.clock = clock\n        self.signal = signal\n        self.bytes = len(self.signal) // 9\n        self.interleaved = interleaved\n        Monitor.__init__(self, callback=callback, event=event)\n\n    def _get_bytes(self):\n        \"\"\"Take a value and extract the individual bytes and control bits.\n\n        Returns a tuple of lists.\n        \"\"\"\n        value = self.signal.value.integer\n        bytes = []\n        ctrls = []\n        byte_shift = 8\n        ctrl_base = 8 * self.bytes\n        ctrl_inc = 1\n        if self.interleaved:\n            byte_shift += 1\n            ctrl_base = 8\n            ctrl_inc = 9\n\n        for i in range(self.bytes):\n            bytes.append((value >> (i * byte_shift)) & 0xff)\n            ctrls.append(bool(value & (1 << ctrl_base)))\n            ctrl_base += ctrl_inc\n\n        return ctrls, bytes\n\n    def _add_payload(self, ctrl, bytes):\n        \"\"\"Take the payload and return true if more to come\"\"\"\n        for index, byte in enumerate(bytes):\n            if ctrl[index]:\n                if byte != _XGMII_TERMINATE:\n                    self.log.error(\"Got control character in XGMII payload\")\n                    self.log.info(\"data = :\" +\n                                  \" \".join([\"%02X\" % b for b in bytes]))\n                    self.log.info(\"ctrl = :\" +\n                                  \" \".join([\"%s\" % str(c) for c in ctrl]))\n                    self._pkt = bytearray()\n                return False\n\n            self._pkt.append(byte)\n        return True\n\n    @cocotb.coroutine\n    def _monitor_recv(self):\n        clk = RisingEdge(self.clock)\n        self._pkt = bytearray()\n\n        while True:\n            yield clk\n            ctrl, bytes = self._get_bytes()\n\n            if ctrl[0] and bytes[0] == _XGMII_START:\n\n                ctrl, bytes = ctrl[1:], bytes[1:]\n\n                while self._add_payload(ctrl, bytes):\n                    yield clk\n                    ctrl, bytes = self._get_bytes()\n\n            elif self.bytes == 8 :\n                if ctrl[4] and bytes[4] == _XGMII_START:\n\n                    ctrl, bytes = ctrl[5:], bytes[5:]\n\n                    while self._add_payload(ctrl, bytes):\n                        yield clk\n                        ctrl, bytes = self._get_bytes()\n\n            if self._pkt:\n\n                self.log.debug(\"Received:\\n%s\" % (hexdump(self._pkt)))\n\n                if len(self._pkt) < 64 + 7:\n                    self.log.error(\"Received a runt frame!\")\n                if len(self._pkt) < 12:\n                    self.log.error(\"No data to extract\")\n                    self._pkt = bytearray()\n                    continue\n\n                preamble_sfd = self._pkt[0:7]\n                crc32 = self._pkt[-4:]\n                payload = self._pkt[7:-4]\n\n                if preamble_sfd != _PREAMBLE_SFD:\n                    self.log.error(\"Got a frame with unknown preamble/SFD\")\n                    self.log.error(hexdump(preamble_sfd))\n                    self._pkt = bytearray()\n                    continue\n\n                expected_crc = struct.pack(\"<I\",\n                                           (zlib.crc32(payload) & 0xFFFFFFFF))\n\n                if crc32 != expected_crc:\n                    self.log.error(\"Incorrect CRC on received packet\")\n                    self.log.info(\"Expected: %s\" % (hexdump(expected_crc)))\n                    self.log.info(\"Received: %s\" % (hexdump(crc32)))\n\n                # Use scapy to decode the packet\n                if _have_scapy:\n                    p = Ether(payload)\n                    self.log.debug(\"Received decoded packet:\\n%s\" % p.show2())\n                else:\n                    p = payload\n\n                self._recv(p)\n                self._pkt = bytearray()\n", "path": "cocotb/monitors/xgmii.py"}]}