split host files since we now have more drivers/dumps supported
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 18 Feb 2015 14:32:34 +0000 (15:32 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 18 Feb 2015 15:49:38 +0000 (16:49 +0100)
21 files changed:
README
litescope/host/driver.py [deleted file]
litescope/host/driver/__init__.py [new file with mode: 0644]
litescope/host/driver/etherbone.py [new file with mode: 0644]
litescope/host/driver/io.py [new file with mode: 0644]
litescope/host/driver/la.py [new file with mode: 0644]
litescope/host/driver/reg.py [new file with mode: 0644]
litescope/host/driver/truthtable.py [new file with mode: 0644]
litescope/host/driver/uart.py [new file with mode: 0644]
litescope/host/dump.py [deleted file]
litescope/host/dump/__init__.py [new file with mode: 0644]
litescope/host/dump/csv.py [new file with mode: 0644]
litescope/host/dump/python.py [new file with mode: 0644]
litescope/host/dump/sigrok.py [new file with mode: 0644]
litescope/host/dump/vcd.py [new file with mode: 0644]
litescope/host/reg.py [deleted file]
litescope/host/truthtable.py [deleted file]
make.py
test/config.py
test/test_io.py
test/test_la.py

diff --git a/README b/README
index 216f4a047562f16540d0f7c39a915176971a7221..6804b3ee515c2777d4bf14bb1cc6d4911a86b76f 100644 (file)
--- a/README
+++ b/README
@@ -7,7 +7,7 @@
                 florent@enjoy-digital.fr
 
        A small footprint and configurable embedded FPGA
-         logic analyzer core developed by EnjoyDigital
+             logic analyzer core powered by Migen
 
 [> Doc
 ---------
diff --git a/litescope/host/driver.py b/litescope/host/driver.py
deleted file mode 100644 (file)
index 0a49fe4..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-import csv
-import time
-import sys
-import string
-import serial
-import socket
-from struct import *
-from migen.fhdl.structure import *
-from litescope.host.reg import *
-from litescope.host.dump import *
-from litescope.host.truthtable import *
-
-# XXX FIXME
-try:
-       from liteeth.test.model.etherbone import *
-except:
-       pass
-
-def write_b(uart, data):
-       uart.write(pack('B',data))
-
-class LiteScopeUART2WBDriver:
-       cmds = {
-               "write" : 0x01,
-               "read"  : 0x02
-       }
-       def __init__(self, port, baudrate=115200, addrmap=None, busword=8, debug=False):
-               self.port = port
-               self.baudrate = str(baudrate)
-               self.debug = debug
-               self.uart = serial.Serial(port, baudrate, timeout=0.25)
-               self.regs = build_map(addrmap, busword, self.read, self.write)
-
-       def open(self):
-               self.uart.flushOutput()
-               self.uart.close()
-               self.uart.open()
-               self.uart.flushInput()
-               try:
-                       self.regs.uart2wb_sel.write(1)
-               except:
-                       pass
-
-       def close(self):
-               try:
-                       self.regs.uart2wb_sel.write(0)
-               except:
-                       pass
-               self.uart.flushOutput()
-               self.uart.close()
-
-       def read(self, addr, burst_length=1):
-               self.uart.flushInput()
-               write_b(self.uart, self.cmds["read"])
-               write_b(self.uart, burst_length)
-               addr = addr//4
-               write_b(self.uart, (addr & 0xff000000) >> 24)
-               write_b(self.uart, (addr & 0x00ff0000) >> 16)
-               write_b(self.uart, (addr & 0x0000ff00) >> 8)
-               write_b(self.uart, (addr & 0x000000ff))
-               values = []
-               for i in range(burst_length):
-                       val = 0
-                       for j in range(4):
-                               val = val << 8
-                               val |= ord(self.uart.read())
-                       if self.debug:
-                               print("RD %08X @ %08X" %(val, (addr+i)*4))
-                       values.append(val)
-               if burst_length == 1:
-                       return values[0]
-               else:
-                       return values
-
-       def write(self, addr, data):
-               if isinstance(data, list):
-                       burst_length = len(data)
-               else:
-                       burst_length = 1
-               write_b(self.uart, self.cmds["write"])
-               write_b(self.uart, burst_length)
-               addr = addr//4
-               write_b(self.uart, (addr & 0xff000000) >> 24)
-               write_b(self.uart, (addr & 0x00ff0000) >> 16)
-               write_b(self.uart, (addr & 0x0000ff00) >> 8)
-               write_b(self.uart, (addr & 0x000000ff))
-               if isinstance(data, list):
-                       for i in range(len(data)):
-                               dat = data[i]
-                               for j in range(4):
-                                       write_b(self.uart, (dat & 0xff000000) >> 24)
-                                       dat = dat << 8
-                               if self.debug:
-                                       print("WR %08X @ %08X" %(data[i], (addr + i)*4))
-               else:
-                       dat = data
-                       for j in range(4):
-                               write_b(self.uart, (dat & 0xff000000) >> 24)
-                               dat = dat << 8
-                       if self.debug:
-                               print("WR %08X @ %08X" %(data, (addr * 4)))
-
-class LiteScopeEtherboneDriver:
-       def __init__(self, ip_address, udp_port=20000, addrmap=None, busword=8, debug=False):
-               self.ip_address = ip_address
-               self.udp_port = udp_port
-               self.debug = debug
-
-               self.tx_sock = None
-               self.rx_sock = None
-               self.regs = build_map(addrmap, busword, self.read, self.write)
-
-       def open(self):
-               self.tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-               self.rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-               self.rx_sock.bind(("", self.udp_port))
-
-       def close(self):
-               pass
-
-       def read(self, addr, burst_length=1):
-               reads_addrs = [addr+4*j for j in range(burst_length)]
-               reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
-               record = EtherboneRecord()
-               record.writes = None
-               record.reads = reads
-               record.bca = 0
-               record.rca = 0
-               record.rff = 0
-               record.cyc = 0
-               record.wca = 0
-               record.wff = 0
-               record.byte_enable = 0xf
-               record.wcount = 0
-               record.rcount = len(reads_addrs)
-
-               packet = EtherbonePacket()
-               packet.records = [record]
-               packet.encode()
-               self.tx_sock.sendto(bytes(packet), (self.ip_address, self.udp_port))
-
-               datas, addrs = self.rx_sock.recvfrom(8192)
-               packet = EtherbonePacket(datas)
-               packet.decode()
-               values = packet.records.pop().writes.get_datas()
-               if self.debug:
-                       for i, val in enumerate(values):
-                               print("RD %08X @ %08X" %(val, addr + 4*i))
-               if burst_length == 1:
-                       return values[0]
-               else:
-                       return values
-
-       def write(self, addr, datas):
-               if not isinstance(datas, list):
-                       datas = [datas]
-               writes_datas = [d for d in datas]
-               writes = EtherboneWrites(base_addr=addr, datas=writes_datas)
-               record = EtherboneRecord()
-               record.writes = writes
-               record.reads = None
-               record.bca = 0
-               record.rca = 0
-               record.rff = 0
-               record.cyc = 0
-               record.wca = 0
-               record.wff = 0
-               record.byte_enable = 0xf
-               record.wcount = len(writes_datas)
-               record.rcount = 0
-
-               packet = EtherbonePacket()
-               packet.records = [record]
-               packet.encode()
-               self.tx_sock.sendto(bytes(packet), (self.ip_address, self.udp_port))
-
-               if self.debug:
-                       for i, data in enumerate(datas):
-                               print("WR %08X @ %08X" %(data, addr + 4*i))
-
-class LiteScopeIODriver():
-       def __init__(self, regs, name):
-               self.regs = regs
-               self.name = name
-               self.build()
-
-       def build(self):
-               for key, value in self.regs.d.items():
-                       if self.name in key:
-                               key = key.replace(self.name +"_", "")
-                               setattr(self, key, value)
-
-       def write(self, value):
-               self.o.write(value)
-
-       def read(self):
-               return self.i.read()
-
-class LiteScopeLADriver():
-       def __init__(self, regs, name, config_csv=None, use_rle=False, debug=False):
-               self.regs = regs
-               self.name = name
-               self.use_rle = use_rle
-               self.debug = debug
-               if config_csv is None:
-                       self.config_csv = name + ".csv"
-               self.get_config()
-               self.get_layout()
-               self.build()
-               self.dat = Dat(self.dw)
-
-       def get_config(self):
-               csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#')
-               for item in csv_reader:
-                       t, n, v = item
-                       if t == "config":
-                               setattr(self, n, int(v))
-
-       def get_layout(self):
-               self.layout = []
-               csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#')
-               for item in csv_reader:
-                       t, n, v = item
-                       if t == "layout":
-                               self.layout.append((n, int(v)))
-
-       def build(self):
-               for key, value in self.regs.d.items():
-                       if self.name == key[:len(self.name)]:
-                               key = key.replace(self.name + "_", "")
-                               setattr(self, key, value)
-               value = 1
-               for name, length in self.layout:
-                       setattr(self, name + "_o", value)
-                       value = value*(2**length)
-               value = 0
-               for name, length in self.layout:
-                       setattr(self, name + "_m", (2**length-1) << value)
-                       value += length
-
-       def configure_term(self, port, trigger=0, mask=0, cond=None):
-               if cond is not None:
-                       for k, v in cond.items():
-                               trigger |= getattr(self, k + "_o")*v
-                               mask |= getattr(self, k + "_m")
-               t = getattr(self, "trigger_port{d}_trig".format(d=int(port)))
-               m = getattr(self, "trigger_port{d}_mask".format(d=int(port)))
-               t.write(trigger)
-               m.write(mask)
-
-       def configure_range_detector(self, port, low, high):
-               l = getattr(self, "trigger_port{d}_low".format(d=int(port)))
-               h = getattr(self, "trigger_port{d}_high".format(d=int(port)))
-               l.write(low)
-               h.write(high)
-
-       def configure_edge_detector(self, port, rising_mask, falling_mask, both_mask):
-               rm = getattr(self, "trigger_port{d}_rising_mask".format(d=int(port)))
-               fm = getattr(self, "trigger_port{d}_falling_mask".format(d=int(port)))
-               bm = getattr(self, "trigger_port{d}_both_mask".format(d=int(port)))
-               rm.write(rising_mask)
-               fm.write(falling_mask)
-               bm.write(both_mask)
-
-       def configure_sum(self, equation):
-               datas = gen_truth_table(equation)
-               for adr, dat in enumerate(datas):
-                       self.trigger_sum_prog_adr.write(adr)
-                       self.trigger_sum_prog_dat.write(dat)
-                       self.trigger_sum_prog_we.write(1)
-
-       def configure_subsampler(self, n):
-               self.subsampler_value.write(n-1)
-
-       def configure_qualifier(self, v):
-               self.recorder_qualifier.write(v)
-
-       def configure_rle(self, v):
-               self.rle_enable.write(v)
-
-       def done(self):
-               return self.recorder_done.read()
-
-       def run(self, offset, length):
-               if self.debug:
-                       print("run")
-               if self.with_rle:
-                       self.config_rle(self.use_rle)
-               self.recorder_offset.write(offset)
-               self.recorder_length.write(length)
-               self.recorder_trigger.write(1)
-
-       def upload(self):
-               if self.debug:
-                       print("upload")
-               while self.recorder_source_stb.read():
-                       self.dat.append(self.recorder_source_data.read())
-                       self.recorder_source_ack.write(1)
-               if self.with_rle:
-                       if self.use_rle:
-                               self.dat = self.dat.decode_rle()
-               return self.dat
-
-       def save(self, filename):
-               if self.debug:
-                       print("save to " + filename)
-               dump = Dump()
-               dump.add_from_layout(self.layout, self.dat)
-               if ".vcd" in filename:
-                       VCDExport(dump).write(filename)
-               elif ".csv" in filename:
-                       CSVExport(dump).write(filename)
-               elif ".py" in filename:
-                       PYExport(dump).write(filename)
-               else:
-                       raise NotImplementedError
diff --git a/litescope/host/driver/__init__.py b/litescope/host/driver/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/litescope/host/driver/etherbone.py b/litescope/host/driver/etherbone.py
new file mode 100644 (file)
index 0000000..02297dd
--- /dev/null
@@ -0,0 +1,82 @@
+import socket
+from litescope.host.driver.reg import *
+
+from liteeth.test.model.etherbone import *
+
+class LiteScopeEtherboneDriver:
+       def __init__(self, ip_address, udp_port=20000, addrmap=None, busword=8, debug=False):
+               self.ip_address = ip_address
+               self.udp_port = udp_port
+               self.debug = debug
+
+               self.tx_sock = None
+               self.rx_sock = None
+               self.regs = build_map(addrmap, busword, self.read, self.write)
+
+       def open(self):
+               self.tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+               self.rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+               self.rx_sock.bind(("", self.udp_port))
+
+       def close(self):
+               pass
+
+       def read(self, addr, burst_length=1):
+               reads_addrs = [addr+4*j for j in range(burst_length)]
+               reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
+               record = EtherboneRecord()
+               record.writes = None
+               record.reads = reads
+               record.bca = 0
+               record.rca = 0
+               record.rff = 0
+               record.cyc = 0
+               record.wca = 0
+               record.wff = 0
+               record.byte_enable = 0xf
+               record.wcount = 0
+               record.rcount = len(reads_addrs)
+
+               packet = EtherbonePacket()
+               packet.records = [record]
+               packet.encode()
+               self.tx_sock.sendto(bytes(packet), (self.ip_address, self.udp_port))
+
+               datas, addrs = self.rx_sock.recvfrom(8192)
+               packet = EtherbonePacket(datas)
+               packet.decode()
+               values = packet.records.pop().writes.get_datas()
+               if self.debug:
+                       for i, val in enumerate(values):
+                               print("RD %08X @ %08X" %(val, addr + 4*i))
+               if burst_length == 1:
+                       return values[0]
+               else:
+                       return values
+
+       def write(self, addr, datas):
+               if not isinstance(datas, list):
+                       datas = [datas]
+               writes_datas = [d for d in datas]
+               writes = EtherboneWrites(base_addr=addr, datas=writes_datas)
+               record = EtherboneRecord()
+               record.writes = writes
+               record.reads = None
+               record.bca = 0
+               record.rca = 0
+               record.rff = 0
+               record.cyc = 0
+               record.wca = 0
+               record.wff = 0
+               record.byte_enable = 0xf
+               record.wcount = len(writes_datas)
+               record.rcount = 0
+
+               packet = EtherbonePacket()
+               packet.records = [record]
+               packet.encode()
+               self.tx_sock.sendto(bytes(packet), (self.ip_address, self.udp_port))
+
+               if self.debug:
+                       for i, data in enumerate(datas):
+                               print("WR %08X @ %08X" %(data, addr + 4*i))
diff --git a/litescope/host/driver/io.py b/litescope/host/driver/io.py
new file mode 100644 (file)
index 0000000..dbee829
--- /dev/null
@@ -0,0 +1,17 @@
+class LiteScopeIODriver():
+       def __init__(self, regs, name):
+               self.regs = regs
+               self.name = name
+               self.build()
+
+       def build(self):
+               for key, value in self.regs.d.items():
+                       if self.name in key:
+                               key = key.replace(self.name +"_", "")
+                               setattr(self, key, value)
+
+       def write(self, value):
+               self.o.write(value)
+
+       def read(self):
+               return self.i.read()
diff --git a/litescope/host/driver/la.py b/litescope/host/driver/la.py
new file mode 100644 (file)
index 0000000..9f6a644
--- /dev/null
@@ -0,0 +1,131 @@
+import csv
+from struct import *
+from migen.fhdl.structure import *
+from litescope.host.dump import *
+from litescope.host.driver.truthtable import *
+
+class LiteScopeLADriver():
+       def __init__(self, regs, name, config_csv=None, use_rle=False, debug=False):
+               self.regs = regs
+               self.name = name
+               self.use_rle = use_rle
+               self.debug = debug
+               if config_csv is None:
+                       self.config_csv = name + ".csv"
+               self.get_config()
+               self.get_layout()
+               self.build()
+               self.dat = Dat(self.dw)
+
+       def get_config(self):
+               csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#')
+               for item in csv_reader:
+                       t, n, v = item
+                       if t == "config":
+                               setattr(self, n, int(v))
+
+       def get_layout(self):
+               self.layout = []
+               csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#')
+               for item in csv_reader:
+                       t, n, v = item
+                       if t == "layout":
+                               self.layout.append((n, int(v)))
+
+       def build(self):
+               for key, value in self.regs.d.items():
+                       if self.name == key[:len(self.name)]:
+                               key = key.replace(self.name + "_", "")
+                               setattr(self, key, value)
+               value = 1
+               for name, length in self.layout:
+                       setattr(self, name + "_o", value)
+                       value = value*(2**length)
+               value = 0
+               for name, length in self.layout:
+                       setattr(self, name + "_m", (2**length-1) << value)
+                       value += length
+
+       def configure_term(self, port, trigger=0, mask=0, cond=None):
+               if cond is not None:
+                       for k, v in cond.items():
+                               trigger |= getattr(self, k + "_o")*v
+                               mask |= getattr(self, k + "_m")
+               t = getattr(self, "trigger_port{d}_trig".format(d=int(port)))
+               m = getattr(self, "trigger_port{d}_mask".format(d=int(port)))
+               t.write(trigger)
+               m.write(mask)
+
+       def configure_range_detector(self, port, low, high):
+               l = getattr(self, "trigger_port{d}_low".format(d=int(port)))
+               h = getattr(self, "trigger_port{d}_high".format(d=int(port)))
+               l.write(low)
+               h.write(high)
+
+       def configure_edge_detector(self, port, rising_mask, falling_mask, both_mask):
+               rm = getattr(self, "trigger_port{d}_rising_mask".format(d=int(port)))
+               fm = getattr(self, "trigger_port{d}_falling_mask".format(d=int(port)))
+               bm = getattr(self, "trigger_port{d}_both_mask".format(d=int(port)))
+               rm.write(rising_mask)
+               fm.write(falling_mask)
+               bm.write(both_mask)
+
+       def configure_sum(self, equation):
+               datas = gen_truth_table(equation)
+               for adr, dat in enumerate(datas):
+                       self.trigger_sum_prog_adr.write(adr)
+                       self.trigger_sum_prog_dat.write(dat)
+                       self.trigger_sum_prog_we.write(1)
+
+       def configure_subsampler(self, n):
+               self.subsampler_value.write(n-1)
+
+       def configure_qualifier(self, v):
+               self.recorder_qualifier.write(v)
+
+       def configure_rle(self, v):
+               self.rle_enable.write(v)
+
+       def done(self):
+               return self.recorder_done.read()
+
+       def run(self, offset, length):
+               if self.debug:
+                       print("running")
+               if self.with_rle:
+                       self.config_rle(self.use_rle)
+               self.recorder_offset.write(offset)
+               self.recorder_length.write(length)
+               self.recorder_trigger.write(1)
+
+       def upload(self):
+               if self.debug:
+                       print("uploading")
+               while self.recorder_source_stb.read():
+                       self.dat.append(self.recorder_source_data.read())
+                       self.recorder_source_ack.write(1)
+               if self.with_rle:
+                       if self.use_rle:
+                               self.dat = self.dat.decode_rle()
+               return self.dat
+
+       def save(self, filename):
+               if self.debug:
+                       print("saving to " + filename)
+               name, ext = os.path.splitext(filename)
+               if ext == ".vcd":
+                       from litescope.host.dump.vcd import VCDDump
+                       dump = VCDDump()
+               elif ext == ".csv":
+                       from litescope.host.dump.csv import CSVDump
+                       dump = CSVDump()
+               elif ext == ".py":
+                       from litescope.host.dump.python import PythonDump
+                       dump = PythonDump()
+               elif ext == ".sr":
+                       from litescope.host.dump.sigrok import SigrokDump
+                       dump = SigrokDump()
+               else:
+                       raise NotImplementedError
+               dump.add_from_layout(self.layout, self.dat)
+               dump.write(filename)
diff --git a/litescope/host/driver/reg.py b/litescope/host/driver/reg.py
new file mode 100644 (file)
index 0000000..16a98d9
--- /dev/null
@@ -0,0 +1,48 @@
+import csv
+
+class MappedReg:
+       def __init__(self, readfn, writefn, name, addr, length, busword, mode):
+               self.readfn = readfn
+               self.writefn = writefn
+               self.addr = addr
+               self.length = length
+               self.busword = busword
+               self.mode = mode
+
+       def read(self):
+               if self.mode not in ["rw", "ro"]:
+                       raise KeyError(name + "register not readable")
+               r = 0
+               for i in range(self.length):
+                       r |= self.readfn(self.addr + 4*i)
+                       if i != (self.length-1):
+                               r <<= self.busword
+               return r
+
+       def write(self, value):
+               if self.mode not in ["rw", "wo"]:
+                       raise KeyError(name + "register not writable")
+               for i in range(self.length):
+                       dat = (value >> ((self.length-1-i)*self.busword)) & (2**self.busword-1)
+                       self.writefn(self.addr + 4*i, dat)
+
+class MappedRegs:
+       def __init__(self, d):
+               self.d = d
+
+       def __getattr__(self, attr):
+               try:
+                       return self.__dict__['d'][attr]
+               except KeyError:
+                       pass
+               raise KeyError("No such register " + attr)
+
+def    build_map(addrmap, busword, readfn, writefn):
+       csv_reader = csv.reader(open(addrmap), delimiter=',', quotechar='#')
+       d = {}
+       for item in csv_reader:
+               name, addr, length, mode = item
+               addr = int(addr.replace("0x", ""), 16)
+               length = int(length)
+               d[name] = MappedReg(readfn, writefn, name, addr, length, busword, mode)
+       return MappedRegs(d)
\ No newline at end of file
diff --git a/litescope/host/driver/truthtable.py b/litescope/host/driver/truthtable.py
new file mode 100644 (file)
index 0000000..3ed6e18
--- /dev/null
@@ -0,0 +1,47 @@
+import os
+import re
+import sys
+
+def is_number(x):
+       try:
+               _ = float(x)
+       except ValueError:
+               return False
+       return True
+
+def remove_numbers(seq):
+       return [x for x in seq if not is_number(x)]
+
+def remove_duplicates(seq):
+       seen = set()
+       seen_add = seen.add
+       return [x for x in seq if x not in seen and not seen_add(x)]
+
+def get_operands(s):
+       operands = re.findall("[A-z0-9_]+", s)
+       operands = remove_duplicates(operands)
+       operands = remove_numbers(operands)
+       return sorted(operands)
+
+def gen_truth_table(s):
+       operands = get_operands(s)
+       width = len(operands)
+       stim = []
+       for i in range(width):
+               stim_op = []
+               for j in range(2**width):
+                       stim_op.append((int(j/(2**i)))%2)
+               stim.append(stim_op)
+
+       truth_table = []
+       for i in range(2**width):
+               for j in range(width):
+                       exec("%s = stim[j][i]" %operands[j])
+               truth_table.append(eval(s) != 0)
+       return truth_table
+
+def main():
+       print(gen_truth_table("(A&B&C)|D"))
+
+if __name__ == '__main__':
+       main()
diff --git a/litescope/host/driver/uart.py b/litescope/host/driver/uart.py
new file mode 100644 (file)
index 0000000..4bd8f71
--- /dev/null
@@ -0,0 +1,87 @@
+import serial
+from struct import *
+from litescope.host.driver.reg import *
+
+def write_b(uart, data):
+       uart.write(pack('B',data))
+
+class LiteScopeUARTDriver:
+       cmds = {
+               "write" : 0x01,
+               "read"  : 0x02
+       }
+       def __init__(self, port, baudrate=115200, addrmap=None, busword=8, debug=False):
+               self.port = port
+               self.baudrate = str(baudrate)
+               self.debug = debug
+               self.uart = serial.Serial(port, baudrate, timeout=0.25)
+               self.regs = build_map(addrmap, busword, self.read, self.write)
+
+       def open(self):
+               self.uart.flushOutput()
+               self.uart.close()
+               self.uart.open()
+               self.uart.flushInput()
+               try:
+                       self.regs.uart2wb_sel.write(1)
+               except:
+                       pass
+
+       def close(self):
+               try:
+                       self.regs.uart2wb_sel.write(0)
+               except:
+                       pass
+               self.uart.flushOutput()
+               self.uart.close()
+
+       def read(self, addr, burst_length=1):
+               self.uart.flushInput()
+               write_b(self.uart, self.cmds["read"])
+               write_b(self.uart, burst_length)
+               addr = addr//4
+               write_b(self.uart, (addr & 0xff000000) >> 24)
+               write_b(self.uart, (addr & 0x00ff0000) >> 16)
+               write_b(self.uart, (addr & 0x0000ff00) >> 8)
+               write_b(self.uart, (addr & 0x000000ff))
+               values = []
+               for i in range(burst_length):
+                       val = 0
+                       for j in range(4):
+                               val = val << 8
+                               val |= ord(self.uart.read())
+                       if self.debug:
+                               print("RD %08X @ %08X" %(val, (addr+i)*4))
+                       values.append(val)
+               if burst_length == 1:
+                       return values[0]
+               else:
+                       return values
+
+       def write(self, addr, data):
+               if isinstance(data, list):
+                       burst_length = len(data)
+               else:
+                       burst_length = 1
+               write_b(self.uart, self.cmds["write"])
+               write_b(self.uart, burst_length)
+               addr = addr//4
+               write_b(self.uart, (addr & 0xff000000) >> 24)
+               write_b(self.uart, (addr & 0x00ff0000) >> 16)
+               write_b(self.uart, (addr & 0x0000ff00) >> 8)
+               write_b(self.uart, (addr & 0x000000ff))
+               if isinstance(data, list):
+                       for i in range(len(data)):
+                               dat = data[i]
+                               for j in range(4):
+                                       write_b(self.uart, (dat & 0xff000000) >> 24)
+                                       dat = dat << 8
+                               if self.debug:
+                                       print("WR %08X @ %08X" %(data[i], (addr + i)*4))
+               else:
+                       dat = data
+                       for j in range(4):
+                               write_b(self.uart, (dat & 0xff000000) >> 24)
+                               dat = dat << 8
+                       if self.debug:
+                               print("WR %08X @ %08X" %(data, (addr * 4)))
diff --git a/litescope/host/dump.py b/litescope/host/dump.py
deleted file mode 100644 (file)
index 9c4f306..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-import sys
-import os
-import math
-import shutil
-import datetime
-import zipfile
-import re
-from collections import OrderedDict
-
-def dec2bin(d, nb=0):
-       if d=="x":
-               return "x"*nb
-       elif d==0:
-               b="0"
-       else:
-               b=""
-               while d!=0:
-                       b="01"[d&1]+b
-                       d=d>>1
-       return b.zfill(nb)
-
-def get_bits(values, width, low, high=None):
-       r = []
-       for val in values:
-               t = dec2bin(val, width)[::-1]
-               if high == None:
-                       t = t[low]
-               else:
-                       t = t[low:high]
-               t = t[::-1]
-               t = int(t,2)
-               r.append(t)
-       return r
-
-class Dat(list):
-       def __init__(self, width):
-               self.width = width
-
-       def __getitem__(self, key):
-               if isinstance(key, int):
-                       return get_bits(self, self.width, key)
-               elif isinstance(key, slice):
-                       if key.start != None:
-                               start = key.start
-                       else:
-                               start = 0
-                       if key.stop != None:
-                               stop = key.stop
-                       else:
-                               stop = self.width
-                       if stop > self.width:
-                               stop = self.width
-                       if key.step != None:
-                               raise KeyError
-                       return get_bits(self, self.width, start, stop)
-               else:
-                       raise KeyError
-
-       def decode_rle(self):
-               rle_bit = self[-1]
-               rle_dat = self[:self.width-1]
-
-               dat = Dat(self.width)
-               i=0
-               last = 0
-               for d in self:
-                       if rle_bit[i]:
-                               if len(dat) >= 1:
-                                       # FIX ME... why is rle_dat in reverse order...
-                                       for j in range(int(dec2bin(rle_dat[i])[::-1],2)):
-                                               dat.append(last)
-                       else:
-                               dat.append(d)
-                               last = d
-                       i +=1
-               return dat
-
-class Var:
-       def __init__(self, name, width, values=[], type="wire", default="x"):
-               self.type = type
-               self.width = width
-               self.name = name
-               self.val = default
-               self.values = values
-               self.vcd_id = None
-
-       def set_vcd_id(self, s):
-               self.vcd_id = s
-
-       def __len__(self):
-               return len(self.values)
-
-       def change(self, cnt):
-               r = ""
-               try :
-                       if self.values[cnt+1] != self.val:
-                               r += "b"
-                               r += dec2bin(self.values[cnt+1], self.width)
-                               r += " "
-                               r += self.vcd_id
-                               r += "\n"
-                               return r
-               except :
-                       return r
-               return r
-
-class Dump:
-       def __init__(self):
-               self.vars = []
-               self.vcd_id = "!"
-
-       def add(self, var):
-               var.set_vcd_id(self.vcd_id)
-               self.vcd_id = chr(ord(self.vcd_id)+1)
-               self.vars.append(var)
-
-       def add_from_layout(self, layout, var):
-               i=0
-               for s, n in layout:
-                       self.add(Var(s, n, var[i:i+n]))
-                       i += n
-
-       def __len__(self):
-               l = 0
-               for var in self.vars:
-                       l = max(len(var),l)
-               return l
-
-class VCDExport():
-       def __init__(self, dump, timescale="1ps", comment=""):
-               self.dump = dump
-               self.timescale = timescale
-               self.comment = comment
-               self.cnt = -1
-
-       def change(self):
-               r = ""
-               c = ""
-               for var in self.dump.vars:
-                       c += var.change(self.cnt)
-               if c != "":
-                       r += "#"
-                       r += str(self.cnt+1)
-                       r += "\n"
-                       r += c
-               return r
-
-       def p_date(self):
-               now = datetime.datetime.now()
-               r = "$date\n"
-               r += "\t"
-               r += now.strftime("%Y-%m-%d %H:%M")
-               r += "\n"
-               r += "$end\n"
-               return r
-
-       def p_version(self):
-               r  = "$version\n"
-               r += "\tmiscope VCD dump\n"
-               r += "$end\n"
-               return r
-
-       def p_comment(self):
-               r  = "$comment\n"
-               r += self.comment
-               r += "\n$end\n"
-               return r
-
-       def p_timescale(self):
-               r  = "$timescale "
-               r += self.timescale
-               r += " $end\n"
-               return r
-
-       def p_scope(self):
-               r  = "$scope "
-               r += self.timescale
-               r += " $end\n"
-               return r
-
-       def  p_vars(self):
-               r = ""
-               for var in self.dump.vars:
-                       r += "$var "
-                       r += var.type
-                       r += " "
-                       r += str(var.width)
-                       r += " "
-                       r += var.vcd_id
-                       r += " "
-                       r += var.name
-                       r += " $end\n"
-               return r
-
-       def p_unscope(self):
-               r  = "$unscope "
-               r += " $end\n"
-               return r
-
-       def p_enddefinitions(self):
-               r  = "$enddefinitions "
-               r += " $end\n"
-               return r
-
-       def p_dumpvars(self):
-               r  = "$dumpvars\n"
-               for var in self.dump.vars:
-                       r += "b"
-                       r += dec2bin(var.val, var.width)
-                       r += " "
-                       r += var.vcd_id
-                       r+= "\n"
-               r += "$end\n"
-               return r
-
-       def p_valuechange(self):
-               r = ""
-               for i in range(len(self.dump)):
-                       r += self.change()
-                       self.cnt += 1
-               return r
-
-       def __repr__(self):
-               r = ""
-               r += self.p_date()
-               r += self.p_version()
-               r += self.p_comment()
-               r += self.p_timescale()
-               r += self.p_scope()
-               r += self.p_vars()
-               r += self.p_unscope()
-               r += self.p_enddefinitions()
-               r += self.p_dumpvars()
-               r += self.p_valuechange()
-               return r
-
-       def write(self, filename):
-               f = open(filename, "w")
-               f.write(str(self))
-               f.close()
-
-class CSVExport():
-       def __init__(self, dump):
-               self.dump = dump
-
-       def  p_vars(self):
-               r = ""
-               for var in self.dump.vars:
-                       r += var.name
-                       r += ","
-               r += "\n"
-               for var in self.dump.vars:
-                       r += str(var.width)
-                       r += ","
-               r += "\n"
-               return r
-
-       def p_dumpvars(self):
-               r  = ""
-               for i in range(len(self.dump)):
-                       for var in self.dump.vars:
-                               try:
-                                       var.val = var.values[i]
-                               except:
-                                       pass
-                               if var.val == "x":
-                                       r += "x"
-                               else:
-                                       r += dec2bin(var.val, var.width)
-                               r += ", "
-                       r+= "\n"
-               return r
-
-       def __repr__(self):
-               r = ""
-               r += self.p_vars()
-               r += self.p_dumpvars()
-               return r
-
-       def write(self, filename):
-               f = open(filename, "w")
-               f.write(str(self))
-               f.close()
-
-class PYExport():
-       def __init__(self, dump):
-               self.dump = dump
-
-       def __repr__(self):
-               r = "dump = {\n"
-               for var in self.dump.vars:
-                       r += "\"" + var.name + "\""
-                       r += " : "
-                       r += str(var.values)
-                       r += ",\n"
-               r += "}"
-               return r
-
-       def write(self, filename):
-               f = open(filename, "w")
-               f.write(str(self))
-               f.close()
-
-class SRExport():
-       def __init__(self, dump):
-               self.dump = dump
-
-       def write_version(self):
-               f = open("version", "w")
-               f.write("1")
-               f.close()
-
-       def write_metadata(self, name):
-               f = open("metadata", "w")
-               r = """
-[global]
-sigrok version = 0.2.0
-[device 1]
-driver = litescope
-capturefile = {}
-unitsize = 1
-total probes = {}
-samplerate = {} MHz
-""".format(
-               name,
-               len(self.dump.vars),
-               50, # XXX add parameter
-       )
-               for i, var in enumerate(self.dump.vars):
-                       r += "probe{} = {}\n".format(i, var.name)
-               f.write(r)
-               f.close()
-
-       def write_data(self, name):
-               # XXX are probes limited to 1 bit?
-               data_bits = math.ceil(len(self.dump.vars)/8)*8
-               data_len = 0
-               for var in self.dump.vars:
-                       data_len = max(data_len, len(var))
-               datas = []
-               for i in range(data_len):
-                       data = 0
-                       for j, var in enumerate(reversed(self.dump.vars)):
-                               data = data << 1
-                               try:
-                                       data |= var.values[i] %2
-                               except:
-                                       pass
-                       datas.append(data)
-
-               f = open(name, "wb")
-               for data in datas:
-                       f.write(data.to_bytes(data_bits//8, "big"))
-               f.close()
-
-       def zip(self, name):
-               f = zipfile.ZipFile(name + ".sr", "w")
-               os.chdir(name)
-               f.write("version")
-               f.write("metadata")
-               f.write(name)
-               os.chdir("..")
-               f.close()
-
-       def write(self, filename):
-               name, ext = os.path.splitext(filename)
-               if os.path.exists(name):
-                       shutil.rmtree(name)
-               os.makedirs(name)
-               os.chdir(name)
-               self.write_version()
-               self.write_metadata(name)
-               self.write_data(name)
-               os.chdir("..")
-               self.zip(name)
-               shutil.rmtree(name)
-
-class SRImport():
-       def __init__(self, filename):
-               name, ext = os.path.splitext(filename)
-               self.unzip(filename, name)
-               os.chdir(name)
-               probes = self.read_metadata()
-               total_probes = len(probes.keys())
-               datas = self.read_data(name, total_probes)
-               os.chdir("..")
-               shutil.rmtree(name)
-               self.dump = self.generate_dump(probes, datas)
-
-       # XXX we can maybe avoid this
-       def unzip(self, filename, name):
-               f = open(filename, "rb")
-               z = zipfile.ZipFile(f)
-               if os.path.exists(name):
-                       shutil.rmtree(name)
-                       os.makedirs(name)
-               for file in z.namelist():
-                       z.extract(file, name)
-               f.close()
-
-       def read_metadata(self):
-               probes = OrderedDict()
-               f = open("metadata", "r")
-               for l in f:
-                       m = re.search("probe([0-9]+) = (\w+)", l, re.I)
-                       if m is not None:
-                               index = int(m.group(1))
-                               name = m.group(2)
-                               probes[name] = index
-               f.close()
-               return probes
-
-       def read_data(self, name, total_probes):
-               datas = []
-               f = open(name, "rb")
-               while True:
-                       data = f.read(math.ceil(total_probes/8))
-                       if data == bytes('', "utf-8"):
-                               break
-                       data = int.from_bytes(data, "big")
-                       datas.append(data)
-               f.close()
-               return datas
-
-       def generate_dump(self, probes, datas):
-               dump = Dump()
-               for k, v in probes.items():
-                       probe_data = []
-                       for data in datas:
-                               probe_data.append((data >> v) & 0x1)
-                       dump.add(Var(k, 1, probe_data))
-               return dump
-
-def main():
-       dump = Dump()
-       dump.add(Var("foo1", 1, [0,1,0,1,0,1]))
-       dump.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]))
-       ramp = [i%128 for i in range(1024)]
-       dump.add(Var("ramp", 16, ramp))
-
-       VCDExport(dump).write("mydump.vcd")
-       CSVExport(dump).write("mydump.csv")
-       PYExport(dump).write("mydump.py")
-       SRExport(dump).write("dump.sr")
-       dump = SRImport("dump.sr").dump
-       VCDExport(dump).write("dump.vcd")
-
-
-if __name__ == '__main__':
-  main()
-
diff --git a/litescope/host/dump/__init__.py b/litescope/host/dump/__init__.py
new file mode 100644 (file)
index 0000000..8e67c9f
--- /dev/null
@@ -0,0 +1,118 @@
+def dec2bin(d, nb=0):
+       if d=="x":
+               return "x"*nb
+       elif d==0:
+               b="0"
+       else:
+               b=""
+               while d!=0:
+                       b="01"[d&1]+b
+                       d=d>>1
+       return b.zfill(nb)
+
+def get_bits(values, width, low, high=None):
+       r = []
+       for val in values:
+               t = dec2bin(val, width)[::-1]
+               if high == None:
+                       t = t[low]
+               else:
+                       t = t[low:high]
+               t = t[::-1]
+               t = int(t,2)
+               r.append(t)
+       return r
+
+class Dat(list):
+       def __init__(self, width):
+               self.width = width
+
+       def __getitem__(self, key):
+               if isinstance(key, int):
+                       return get_bits(self, self.width, key)
+               elif isinstance(key, slice):
+                       if key.start != None:
+                               start = key.start
+                       else:
+                               start = 0
+                       if key.stop != None:
+                               stop = key.stop
+                       else:
+                               stop = self.width
+                       if stop > self.width:
+                               stop = self.width
+                       if key.step != None:
+                               raise KeyError
+                       return get_bits(self, self.width, start, stop)
+               else:
+                       raise KeyError
+
+       def decode_rle(self):
+               rle_bit = self[-1]
+               rle_dat = self[:self.width-1]
+
+               dat = Dat(self.width)
+               i=0
+               last = 0
+               for d in self:
+                       if rle_bit[i]:
+                               if len(dat) >= 1:
+                                       # FIX ME... why is rle_dat in reverse order...
+                                       for j in range(int(dec2bin(rle_dat[i])[::-1],2)):
+                                               dat.append(last)
+                       else:
+                               dat.append(d)
+                               last = d
+                       i +=1
+               return dat
+
+class Var:
+       def __init__(self, name, width, values=[], type="wire", default="x"):
+               self.type = type
+               self.width = width
+               self.name = name
+               self.val = default
+               self.values = values
+               self.vcd_id = None
+
+       def set_vcd_id(self, s):
+               self.vcd_id = s
+
+       def __len__(self):
+               return len(self.values)
+
+       def change(self, cnt):
+               r = ""
+               try :
+                       if self.values[cnt+1] != self.val:
+                               r += "b"
+                               r += dec2bin(self.values[cnt+1], self.width)
+                               r += " "
+                               r += self.vcd_id
+                               r += "\n"
+                               return r
+               except :
+                       return r
+               return r
+
+class Dump:
+       def __init__(self):
+               self.vars = []
+               self.vcd_id = "!"
+
+       def add(self, var):
+               var.set_vcd_id(self.vcd_id)
+               self.vcd_id = chr(ord(self.vcd_id)+1)
+               self.vars.append(var)
+
+       def add_from_layout(self, layout, var):
+               i=0
+               for s, n in layout:
+                       self.add(Var(s, n, var[i:i+n]))
+                       i += n
+
+       def __len__(self):
+               l = 0
+               for var in self.vars:
+                       l = max(len(var),l)
+               return l
diff --git a/litescope/host/dump/csv.py b/litescope/host/dump/csv.py
new file mode 100644 (file)
index 0000000..8face7f
--- /dev/null
@@ -0,0 +1,52 @@
+from litescope.host.dump import *
+
+class CSVDump(Dump):
+       def __init__(self, init_dump=None):
+               Dump.__init__(self)
+               if init_dump:
+                       self.vars = init_dump.vars
+
+       def  generate_vars(self):
+               r = ""
+               for var in self.vars:
+                       r += var.name
+                       r += ","
+               r += "\n"
+               for var in self.vars:
+                       r += str(var.width)
+                       r += ","
+               r += "\n"
+               return r
+
+       def generate_dumpvars(self):
+               r  = ""
+               for i in range(len(self)):
+                       for var in self.vars:
+                               try:
+                                       var.val = var.values[i]
+                               except:
+                                       pass
+                               if var.val == "x":
+                                       r += "x"
+                               else:
+                                       r += dec2bin(var.val, var.width)
+                               r += ", "
+                       r+= "\n"
+               return r
+
+       def write(self, filename):
+               f = open(filename, "w")
+               f.write(self.generate_vars())
+               f.write(self.generate_dumpvars())
+               f.close()
+
+       def read(self, filename):
+               raise NotImplementedError("CSV files can not (yet) be read, please contribute!")
+
+if __name__ == '__main__':
+       dump = CSVDump()
+       dump.add(Var("foo1", 1, [0,1,0,1,0,1]))
+       dump.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]))
+       ramp = [i%128 for i in range(1024)]
+       dump.add(Var("ramp", 16, ramp))
+       dump.write("dump.csv")
diff --git a/litescope/host/dump/python.py b/litescope/host/dump/python.py
new file mode 100644 (file)
index 0000000..0dd9cdd
--- /dev/null
@@ -0,0 +1,33 @@
+from litescope.host.dump import *
+
+class PythonDump(Dump):
+       def __init__(self, init_dump=None):
+               Dump.__init__(self)
+               if init_dump:
+                       self.vars = init_dump.vars
+
+       def generate_data(self):
+               r = "dump = {\n"
+               for var in self.vars:
+                       r += "\"" + var.name + "\""
+                       r += " : "
+                       r += str(var.values)
+                       r += ",\n"
+               r += "}"
+               return r
+
+       def write(self, filename):
+               f = open(filename, "w")
+               f.write(self.generate_data())
+               f.close()
+
+       def read(self, filename):
+               raise NotImplementedError("Python files can not (yet) be read, please contribute!")
+
+if __name__ == '__main__':
+       dump = PythonDump()
+       dump.add(Var("foo1", 1, [0,1,0,1,0,1]))
+       dump.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]))
+       ramp = [i%128 for i in range(1024)]
+       dump.add(Var("ramp", 16, ramp))
+       dump.write("dump.py")
diff --git a/litescope/host/dump/sigrok.py b/litescope/host/dump/sigrok.py
new file mode 100644 (file)
index 0000000..0d664ce
--- /dev/null
@@ -0,0 +1,143 @@
+import os
+import math
+import shutil
+import zipfile
+import re
+from collections import OrderedDict
+
+from litescope.host.dump import *
+
+class SigrokDump(Dump):
+       def __init__(self, init_dump=None):
+               Dump.__init__(self)
+               if init_dump:
+                       self.vars = init_dump.vars
+
+       def write_version(self):
+               f = open("version", "w")
+               f.write("1")
+               f.close()
+
+       def write_metadata(self, name):
+               f = open("metadata", "w")
+               r = """
+[global]
+sigrok version = 0.2.0
+[device 1]
+driver = litescope
+capturefile = {}
+unitsize = 1
+total probes = {}
+samplerate = {} MHz
+""".format(
+               name,
+               len(self.vars),
+               50, # XXX add parameter
+       )
+               for i, var in enumerate(self.vars):
+                       r += "probe{} = {}\n".format(i, var.name)
+               f.write(r)
+               f.close()
+
+       def write_data(self, name):
+               # XXX are probes limited to 1 bit?
+               data_bits = math.ceil(len(self.vars)/8)*8
+               data_len = 0
+               for var in self.vars:
+                       data_len = max(data_len, len(var))
+               datas = []
+               for i in range(data_len):
+                       data = 0
+                       for j, var in enumerate(reversed(self.vars)):
+                               data = data << 1
+                               try:
+                                       data |= var.values[i] %2
+                               except:
+                                       pass
+                       datas.append(data)
+               f = open(name, "wb")
+               for data in datas:
+                       f.write(data.to_bytes(data_bits//8, "big"))
+               f.close()
+
+       def zip(self, name):
+               f = zipfile.ZipFile(name + ".sr", "w")
+               os.chdir(name)
+               f.write("version")
+               f.write("metadata")
+               f.write(name)
+               os.chdir("..")
+               f.close()
+
+       def write(self, filename):
+               name, ext = os.path.splitext(filename)
+               if os.path.exists(name):
+                       shutil.rmtree(name)
+               os.makedirs(name)
+               os.chdir(name)
+               self.write_version()
+               self.write_metadata(name)
+               self.write_data(name)
+               os.chdir("..")
+               self.zip(name)
+               shutil.rmtree(name)
+
+       def unzip(self, filename, name):
+               f = open(filename, "rb")
+               z = zipfile.ZipFile(f)
+               if os.path.exists(name):
+                       shutil.rmtree(name)
+                       os.makedirs(name)
+               for file in z.namelist():
+                       z.extract(file, name)
+               f.close()
+
+       def read_metadata(self):
+               probes = OrderedDict()
+               f = open("metadata", "r")
+               for l in f:
+                       m = re.search("probe([0-9]+) = (\w+)", l, re.I)
+                       if m is not None:
+                               index = int(m.group(1))
+                               name = m.group(2)
+                               probes[name] = index
+               f.close()
+               return probes
+
+       def read_data(self, name, total_probes):
+               datas = []
+               f = open(name, "rb")
+               while True:
+                       data = f.read(math.ceil(total_probes/8))
+                       if data == bytes('', "utf-8"):
+                               break
+                       data = int.from_bytes(data, "big")
+                       datas.append(data)
+               f.close()
+               return datas
+
+       def read(self, filename):
+               self.vars = []
+               name, ext = os.path.splitext(filename)
+               self.unzip(filename, name)
+               os.chdir(name)
+               probes = self.read_metadata()
+               datas = self.read_data(name, len(probes.keys()))
+               os.chdir("..")
+               shutil.rmtree(name)
+
+               for k, v in probes.items():
+                       probe_data = []
+                       for data in datas:
+                               probe_data.append((data >> v) & 0x1)
+                       self.add(Var(k, 1, probe_data))
+
+if __name__ == '__main__':
+       dump = SigrokDump()
+       dump.add(Var("foo1", 1, [0,1,0,1,0,1]))
+       dump.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]))
+       ramp = [i%128 for i in range(1024)]
+       dump.add(Var("ramp", 16, ramp))
+       dump.write("dump.sr")
+       dump.read("dump.sr")
+       dump.write("dump_copy.sr")
diff --git a/litescope/host/dump/vcd.py b/litescope/host/dump/vcd.py
new file mode 100644 (file)
index 0000000..1646eb9
--- /dev/null
@@ -0,0 +1,127 @@
+import datetime
+from litescope.host.dump import *
+
+class VCDDump(Dump):
+       def __init__(self, init_dump=None, timescale="1ps", comment=""):
+               Dump.__init__(self)
+               if init_dump:
+                       self.vars = init_dump.vars
+               self.timescale = timescale
+               self.comment = comment
+               self.cnt = -1
+
+       def change(self):
+               r = ""
+               c = ""
+               for var in self.vars:
+                       c += var.change(self.cnt)
+               if c != "":
+                       r += "#"
+                       r += str(self.cnt+1)
+                       r += "\n"
+                       r += c
+               return r
+
+       def generate_date(self):
+               now = datetime.datetime.now()
+               r = "$date\n"
+               r += "\t"
+               r += now.strftime("%Y-%m-%d %H:%M")
+               r += "\n"
+               r += "$end\n"
+               return r
+
+       def generate_version(self):
+               r  = "$version\n"
+               r += "\tmiscope VCD dump\n"
+               r += "$end\n"
+               return r
+
+       def generate_comment(self):
+               r  = "$comment\n"
+               r += self.comment
+               r += "\n$end\n"
+               return r
+
+       def generate_timescale(self):
+               r  = "$timescale "
+               r += self.timescale
+               r += " $end\n"
+               return r
+
+       def generate_scope(self):
+               r  = "$scope "
+               r += self.timescale
+               r += " $end\n"
+               return r
+
+       def generate_vars(self):
+               r = ""
+               for var in self.vars:
+                       r += "$var "
+                       r += var.type
+                       r += " "
+                       r += str(var.width)
+                       r += " "
+                       r += var.vcd_id
+                       r += " "
+                       r += var.name
+                       r += " $end\n"
+               return r
+
+       def generate_unscope(self):
+               r  = "$unscope "
+               r += " $end\n"
+               return r
+
+       def generate_enddefinitions(self):
+               r  = "$enddefinitions "
+               r += " $end\n"
+               return r
+
+       def generate_dumpvars(self):
+               r  = "$dumpvars\n"
+               for var in self.vars:
+                       r += "b"
+                       r += dec2bin(var.val, var.width)
+                       r += " "
+                       r += var.vcd_id
+                       r+= "\n"
+               r += "$end\n"
+               return r
+
+       def generate_valuechange(self):
+               r = ""
+               for i in range(len(self)):
+                       r += self.change()
+                       self.cnt += 1
+               return r
+
+       def __repr__(self):
+               r = ""
+
+               return r
+
+       def write(self, filename):
+               f = open(filename, "w")
+               f.write(self.generate_date())
+               f.write(self.generate_comment())
+               f.write(self.generate_timescale())
+               f.write(self.generate_scope())
+               f.write(self.generate_vars())
+               f.write(self.generate_unscope())
+               f.write(self.generate_enddefinitions())
+               f.write(self.generate_dumpvars())
+               f.write(self.generate_valuechange())
+               f.close()
+
+       def read(self, filename):
+               raise NotImplementedError("VCD files can not (yet) be read, please contribute!")
+
+if __name__ == '__main__':
+       dump = VCDDump()
+       dump.add(Var("foo1", 1, [0,1,0,1,0,1]))
+       dump.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]))
+       ramp = [i%128 for i in range(1024)]
+       dump.add(Var("ramp", 16, ramp))
+       dump.write("dump.vcd")
diff --git a/litescope/host/reg.py b/litescope/host/reg.py
deleted file mode 100644 (file)
index 16a98d9..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-import csv
-
-class MappedReg:
-       def __init__(self, readfn, writefn, name, addr, length, busword, mode):
-               self.readfn = readfn
-               self.writefn = writefn
-               self.addr = addr
-               self.length = length
-               self.busword = busword
-               self.mode = mode
-
-       def read(self):
-               if self.mode not in ["rw", "ro"]:
-                       raise KeyError(name + "register not readable")
-               r = 0
-               for i in range(self.length):
-                       r |= self.readfn(self.addr + 4*i)
-                       if i != (self.length-1):
-                               r <<= self.busword
-               return r
-
-       def write(self, value):
-               if self.mode not in ["rw", "wo"]:
-                       raise KeyError(name + "register not writable")
-               for i in range(self.length):
-                       dat = (value >> ((self.length-1-i)*self.busword)) & (2**self.busword-1)
-                       self.writefn(self.addr + 4*i, dat)
-
-class MappedRegs:
-       def __init__(self, d):
-               self.d = d
-
-       def __getattr__(self, attr):
-               try:
-                       return self.__dict__['d'][attr]
-               except KeyError:
-                       pass
-               raise KeyError("No such register " + attr)
-
-def    build_map(addrmap, busword, readfn, writefn):
-       csv_reader = csv.reader(open(addrmap), delimiter=',', quotechar='#')
-       d = {}
-       for item in csv_reader:
-               name, addr, length, mode = item
-               addr = int(addr.replace("0x", ""), 16)
-               length = int(length)
-               d[name] = MappedReg(readfn, writefn, name, addr, length, busword, mode)
-       return MappedRegs(d)
\ No newline at end of file
diff --git a/litescope/host/truthtable.py b/litescope/host/truthtable.py
deleted file mode 100644 (file)
index 3ed6e18..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-import os
-import re
-import sys
-
-def is_number(x):
-       try:
-               _ = float(x)
-       except ValueError:
-               return False
-       return True
-
-def remove_numbers(seq):
-       return [x for x in seq if not is_number(x)]
-
-def remove_duplicates(seq):
-       seen = set()
-       seen_add = seen.add
-       return [x for x in seq if x not in seen and not seen_add(x)]
-
-def get_operands(s):
-       operands = re.findall("[A-z0-9_]+", s)
-       operands = remove_duplicates(operands)
-       operands = remove_numbers(operands)
-       return sorted(operands)
-
-def gen_truth_table(s):
-       operands = get_operands(s)
-       width = len(operands)
-       stim = []
-       for i in range(width):
-               stim_op = []
-               for j in range(2**width):
-                       stim_op.append((int(j/(2**i)))%2)
-               stim.append(stim_op)
-
-       truth_table = []
-       for i in range(2**width):
-               for j in range(width):
-                       exec("%s = stim[j][i]" %operands[j])
-               truth_table.append(eval(s) != 0)
-       return truth_table
-
-def main():
-       print(gen_truth_table("(A&B&C)|D"))
-
-if __name__ == '__main__':
-       main()
diff --git a/make.py b/make.py
index f6f84f5c821fcdcc65e8561c3cf61348acf7c52f..f3f6304c463d6ebc23843a98c176ef47da066202 100644 (file)
--- a/make.py
+++ b/make.py
@@ -90,7 +90,7 @@ if __name__ == "__main__":
                               /_/
 
    A small footprint and configurable embedded FPGA
-            based in Migen/MiSoC
+       logic analyzer core powered by Migen
 
 ====== Building parameters: ======
 LiscopeIO
index 7fc570687584493082df8e0e8a18370fc411da00..fb98ad1dffdbed5e387bc2b39ced471917b49b11 100644 (file)
@@ -1,4 +1,4 @@
-from litescope.host.driver import LiteScopeUART2WBDriver
+from litescope.host.driver.uart import LiteScopeUARTDriver
 
 csr_csv_file = "./csr.csv"
 busword = 32
@@ -6,4 +6,4 @@ debug_wb = False
 
 com = 3
 baud = 115200
-wb = LiteScopeUART2WBDriver(com, baud, csr_csv_file, busword, debug_wb)
\ No newline at end of file
+wb = LiteScopeUARTDriver(com, baud, csr_csv_file, busword, debug_wb)
\ No newline at end of file
index 8f3f2e0ca1f3ff5103ebeb0e4feffb66f21df38b..431c6cb6a02be77e781ef737e25ae2b073fbf079 100644 (file)
@@ -1,7 +1,7 @@
 import time
 
 from config import *
-from litescope.host.driver import LiteScopeIODriver
+from litescope.host.driver.io import LiteScopeIODriver
 
 def led_anim0(io):
        for i in range(10):
index 48b7a9ba250be9ecfdf1235262ef105dc704c27a..aa29b46b9a2d0e7e435292a13d3673fd7a0d8d09 100644 (file)
@@ -1,5 +1,5 @@
 from config import *
-from litescope.host.driver import LiteScopeLADriver
+from litescope.host.driver.la import LiteScopeLADriver
 
 wb.open()
 ###
@@ -19,5 +19,6 @@ la.upload()
 la.save("dump.vcd")
 la.save("dump.csv")
 la.save("dump.py")
+la.save("dump.sr")
 ###
 wb.close()