From: Florent Kermarrec Date: Tue, 17 Jun 2014 09:25:10 +0000 (+0200) Subject: host: split read/export and add csv export X-Git-Tag: 24jan2021_ls180~2575^2~71 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a7373589193fc0a65420185367e96b256bc80095;p=litex.git host: split read/export and add csv export --- diff --git a/miscope/host/drivers.py b/miscope/host/drivers.py index 7668af67..423b7d39 100644 --- a/miscope/host/drivers.py +++ b/miscope/host/drivers.py @@ -1,7 +1,7 @@ import csv import time import sys -from miscope.host.vcd import * +from miscope.host.export import * from miscope.host.truthtable import * class MiIoDriver(): @@ -23,20 +23,19 @@ class MiIoDriver(): return self.miio_i.read() class MiLaDriver(): - def __init__(self, regs, name, csv_name=None, use_rle=True): + def __init__(self, regs, name, config_csv=None, use_rle=True): self.regs = regs self.name = name self.use_rle = use_rle - - if csv_name is None: - self.csv = name + ".csv" + if config_csv is None: + self.config_csv = name + ".csv" self.get_config() self.get_layout() self.build_mila() - self.dat = VcdDat(self.width) + self.dat = Dat(self.width) def get_config(self): - csv_reader = csv.reader(open(self.csv), delimiter=',', quotechar='#') + csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#') for item in csv_reader: t, n, v = item if t == "config": @@ -44,7 +43,7 @@ class MiLaDriver(): def get_layout(self): self.layout = [] - csv_reader = csv.reader(open(self.csv), delimiter=',', quotechar='#') + csv_reader = csv.reader(open(self.config_csv), delimiter=',', quotechar='#') for item in csv_reader: t, n, v = item if t == "layout": @@ -64,10 +63,8 @@ class MiLaDriver(): setattr(self, name+"_m", (2**length-1) << value) value += length - def show_state(self, s, last=False): - print(s, end="") - if not last: - print("-->", end="") + def show_state(self, s): + print(s, end="|") sys.stdout.flush() def prog_term(self, port, trigger, mask): @@ -116,8 +113,8 @@ class MiLaDriver(): self.mila_recorder_length.write(length) self.mila_recorder_trigger.write(1) - def read(self, vcd=None): - self.show_state("READ", last=not vcd) + def read(self): + self.show_state("READ") empty = self.mila_recorder_read_empty.read() while(not empty): self.dat.append(self.mila_recorder_read_dat.read()) @@ -125,8 +122,17 @@ class MiLaDriver(): self.mila_recorder_read_en.write(1) if self.use_rle: self.dat = self.dat.decode_rle() - if vcd: - self.show_state("OUTPUT", last=True) - _vcd = Vcd() - _vcd.add_from_layout(self.layout, self.dat) - _vcd.write(vcd) + return self.dat + + def export(self, export_fn=None): + self.show_state("EXPORT") + if ".vcd" in export_fn: + vcd = VCD() + vcd.add_from_layout(self.layout, self.dat) + vcd.write(export_fn) + elif ".csv" in export_fn: + csv = CSV() + csv.add_from_layout(self.layout, self.dat) + csv.write(export_fn) + else: + raise NotImplementedError diff --git a/miscope/host/export.py b/miscope/host/export.py new file mode 100644 index 00000000..d9b80509 --- /dev/null +++ b/miscope/host/export.py @@ -0,0 +1,313 @@ +import sys +import datetime + +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)[::-1] + r += " " + r += self.vcd_id + r += "\n" + return r + except : + return r + return r + +class VCD: + def __init__(self, timescale="1ps", comment=""): + self.timescale = timescale + self.comment = comment + self.vars = [] + self.vcd_id = "!" + self.cnt = -1 + + 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 + + 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 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.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.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)): + 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 CSV: + def __init__(self): + self.vars = [] + self.cnt = -1 + + def add(self, var): + 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 + + def p_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 p_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 __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() + +def main(): + myvcd = VCD() + myvcd.add(Var("foo1", 1, [0,1,0,1,0,1])) + myvcd.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0])) + myvcd.add(Var("foo3", 3)) + myvcd.add(Var("foo4", 4)) + ramp = [i%128 for i in range(1024)] + myvcd.add(Var("ramp", 16, ramp)) + print(myvcd) + + mycsv = CSV() + mycsv.add(Var("foo1", 1, [0,1,0,1,0,1])) + mycsv.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0])) + mycsv.add(Var("foo3", 3)) + mycsv.add(Var("foo4", 4)) + ramp = [i%128 for i in range(1024)] + mycsv.add(Var("ramp", 16, ramp)) + print(mycsv) + + +if __name__ == '__main__': + main() + diff --git a/miscope/host/vcd.py b/miscope/host/vcd.py deleted file mode 100644 index 0259e609..00000000 --- a/miscope/host/vcd.py +++ /dev/null @@ -1,244 +0,0 @@ -import sys -import datetime - -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 VcdDat(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 = VcdDat(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)[::-1] - r += " " - r += self.vcd_id - r += "\n" - return r - except : - return r - return r - -class Vcd: - def __init__(self, timescale="1ps", comment=""): - self.timescale = timescale - self.comment = comment - self.vars = [] - self.vcd_id = "!" - self.cnt = -1 - - 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 - - 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 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.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.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)): - 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() - -def main(): - myvcd = Vcd() - myvcd.add(Var("foo1", 1, [0,1,0,1,0,1])) - myvcd.add(Var("foo2", 2, [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0])) - myvcd.add(Var("foo3", 3)) - myvcd.add(Var("foo4", 4)) - ramp = [i%128 for i in range(1024)] - myvcd.add(Var("ramp", 16, ramp)) - print(myvcd) - -if __name__ == '__main__': - main() -