litescope: add PCIe driver (mmap/Sysfs) and use it on litepcie example design
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Sat, 18 Apr 2015 11:53:14 +0000 (13:53 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Sat, 18 Apr 2015 11:58:20 +0000 (13:58 +0200)
misoclib/com/litepcie/example_designs/test/make.py
misoclib/tools/litescope/host/driver/pcie.py [new file with mode: 0644]

index aa3c5cceff0531bbf922f8a33df57844692864b8..f29f45a06defe63e392d4461a671b4ad8ef1e50c 100644 (file)
@@ -10,6 +10,8 @@ def _get_args():
     parser.add_argument("--baudrate", default=115200, help="UART baudrate")
     parser.add_argument("--ip_address", default="192.168.0.42", help="Etherbone IP address")
     parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port")
+    parser.add_argument("--bar", default="/sys/bus/pci/devices/0000:04:00.0/resource0", help="PCIe BAR")
+    parser.add_argument("--bar_size", default=1*1024*1024, help="PCIe BAR size")
     parser.add_argument("--busword", default=32, help="CSR busword")
 
     parser.add_argument("test", nargs="+", help="specify a test")
@@ -25,6 +27,9 @@ if __name__ == "__main__":
     elif args.bridge == "etherbone":
         from misoclib.tools.litescope.host.driver.etherbone import LiteScopeEtherboneDriver
         wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False)
+    elif args.bridge == "pcie":
+        from misoclib.tools.litescope.host.driver.pcie import LiteScopePCIeDriver
+        wb = LiteScopePCIeDriver(args.bar, args.bar_size, "./csr.csv", int(args.busword), debug=False)
     else:
         ValueError("Invalid bridge {}".format(args.bridge))
 
diff --git a/misoclib/tools/litescope/host/driver/pcie.py b/misoclib/tools/litescope/host/driver/pcie.py
new file mode 100644 (file)
index 0000000..97063aa
--- /dev/null
@@ -0,0 +1,55 @@
+import string
+import mmap
+from misoclib.tools.litescope.host.driver.reg import *
+
+
+class LiteScopePCIeDriver:
+    def __init__(self, bar, bar_size, addrmap=None, busword=8, debug=False):
+        self.bar = bar
+        self.bar_size = bar_size
+        self.debug = debug
+        self.f = None
+        self.mmap = None
+        self.regs = build_map(addrmap, busword, self.read, self.write)
+
+    def open(self):
+        self.f = open(self.bar, "r+b")
+        self.f.flush()
+        self.mmap = mmap.mmap(self.f.fileno(), self.bar_size)
+
+    def close(self):
+        self.mmap.close()
+        self.f.close()
+
+    def read(self, addr, burst_length=None, repeats=None):
+        if repeats is not None:
+            raise NotImplementedError
+        values = []
+        for i in range(burst_length):
+            self.mmap.seek(addr + 4*i)
+            dat = self.mmap.read(4)
+            val = dat[3] << 24
+            val |= dat[2] << 16
+            val |= dat[1] << 8
+            val |= dat[0] << 0
+            if self.debug:
+                print("RD {:08X} @ {:08X}".format(val, addr + 4*i))
+            values.append(val)
+        return values
+
+    def write(self, addr, data):
+        if isinstance(data, list):
+            burst_length = len(data)
+        else:
+            burst_length = 1
+            data = [data]
+
+        for i, dat in enumerate(data):
+            dat_bytes = [0, 0, 0, 0]
+            dat_bytes[3] = (dat >> 24) & 0xff
+            dat_bytes[2] = (dat >> 16) & 0xff
+            dat_bytes[1] = (dat >> 8) & 0xff
+            dat_bytes[0] = (dat >> 0) & 0xff
+            self.mmap[addr + 4*i:addr + 4*(i+1)] = bytes(dat_bytes)
+            if self.debug:
+                print("WR {:08X} @ {:08X}".format(dat, (addr + i)*4))