From f4e6cebab2930696b0e147b575f7fe6b4f8d4890 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 3 Aug 2014 08:38:37 +0200 Subject: [PATCH] clean up --- README | 14 +++++------ miscope/host/dump.py | 24 +++++++++--------- miscope/host/regs.py | 1 - miscope/host/truthtable.py | 14 +++++------ miscope/host/uart2wishbone.py | 2 +- miscope/miio.py | 4 +-- miscope/mila.py | 5 ++-- miscope/std.py | 30 ++++++++--------------- miscope/storage.py | 11 +++++---- miscope/trigger.py | 46 ++++++++++++++++------------------- miscope/uart2wishbone.py | 32 +++++++++--------------- 11 files changed, 80 insertions(+), 103 deletions(-) diff --git a/README b/README index 196b9adc..89510070 100644 --- a/README +++ b/README @@ -15,18 +15,18 @@ Miscope is a small logic analyzer to embed in an FPGA. While free vendor toolchains are generally used by beginners or for prototyping -(situations where having a logic analyser in the design is generally helpful) +(situations where having a logic analyzer in the design is generally helpful) free toolchains are always provided without the proprietary logic analyzer solution... :( -Based on Migen, Miscope aims to provide a free, portable and flexible -alternative to vendor's solutions! +Baseid on Migen, Miscope aims to provide a free, portable and flexible +alternatve to vendor's solutions! [> Specification: Miscope provides Migen cores to embed in the design and Python drivers to control the logic analyzer from the Host. Miscope automatically interconnects all cores -to a CSR bus. When using Python on the Host, no needs to worry aboutcores register +to a CSR bus. When using Python on the Host, no needs to worry about cores register mapping, importing miscope project gives you direct access to all the cores! Miscope produces .vcd output files to be analyzed in your favorite waveform viewer. @@ -35,14 +35,14 @@ Since Miscope also provides an Uart2Wishbone bridge, you only need 2 external Rx pins to be ready to debug! [> Status: -Miio & Mila working on board with standard term. +MiIo & Mila working on board with standard term. RLE working on board. RangeDetector and EdgeDector terms not tested. [> Examples: Have a look at http://github.com/Florent-Kermarrec/misoc-de0nano -miscope_miio.py : Led & Switch Test controlled by Python Host. -miscope_mila.py : Logic Analyzer controlled by Python Host. +miio.py : Led & Switch Test controlled by Python Host. +mila.py : Logic Analyzer controlled by Python Host. [> Contact E-mail: florent@enjoy-digital.fr diff --git a/miscope/host/dump.py b/miscope/host/dump.py index eef6e057..77a6e309 100644 --- a/miscope/host/dump.py +++ b/miscope/host/dump.py @@ -67,7 +67,7 @@ class Dat(list): dat.append(d) last = d i +=1 - return dat + return dat class Var: def __init__(self, name, width, values=[], type="wire", default="x"): @@ -147,25 +147,25 @@ class VCDExport(): 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 @@ -185,17 +185,17 @@ class VCDExport(): 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: @@ -206,7 +206,7 @@ class VCDExport(): r+= "\n" r += "$end\n" return r - + def p_valuechange(self): r = "" for i in range(len(self.dump)): @@ -248,7 +248,7 @@ class CSVExport(): r += "," r += "\n" return r - + def p_dumpvars(self): r = "" for i in range(len(self.dump)): @@ -293,7 +293,7 @@ class PYExport(): def write(self, filename): f = open(filename, "w") f.write(str(self)) - f.close() + f.close() def main(): dump = Dump() @@ -305,7 +305,7 @@ def main(): VCDExport(dump).write("mydump.vcd") CSVExport(dump).write("mydump.csv") PYExport(dump).write("mydump.py") - + if __name__ == '__main__': main() diff --git a/miscope/host/regs.py b/miscope/host/regs.py index 0eaef444..16a98d91 100644 --- a/miscope/host/regs.py +++ b/miscope/host/regs.py @@ -35,7 +35,6 @@ class MappedRegs: return self.__dict__['d'][attr] except KeyError: pass - raise KeyError("No such register " + attr) def build_map(addrmap, busword, readfn, writefn): diff --git a/miscope/host/truthtable.py b/miscope/host/truthtable.py index 14ce7969..319eaee7 100644 --- a/miscope/host/truthtable.py +++ b/miscope/host/truthtable.py @@ -3,19 +3,19 @@ import re import sys def is_number(x): - try: - _ = float(x) - except ValueError: - return False - return True + try: + _ = float(x) + except ValueError: + return False + return True def remove_numbers(seq): - return [ x for x in seq if not is_number(x)] + 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)] + 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) diff --git a/miscope/host/uart2wishbone.py b/miscope/host/uart2wishbone.py index 01fa0103..03c33a8e 100644 --- a/miscope/host/uart2wishbone.py +++ b/miscope/host/uart2wishbone.py @@ -26,7 +26,7 @@ class Uart2Wishbone: self.regs.uart2wb_sel.write(1) except: pass - + def close(self): try: self.regs.uart2wb_sel.write(0) diff --git a/miscope/miio.py b/miscope/miio.py index 60e0141e..b2dbb721 100644 --- a/miscope/miio.py +++ b/miscope/miio.py @@ -11,7 +11,7 @@ class MiIo(Module, AutoCSR): self._r_i = CSRStatus(width) self._r_o = CSRStorage(width) - self.sync +=[ + self.sync += [ self._r_i.status.eq(self.i), self.o.eq(self._r_o.storage) - ] \ No newline at end of file + ] diff --git a/miscope/mila.py b/miscope/mila.py index 457b317a..3edbdd90 100644 --- a/miscope/mila.py +++ b/miscope/mila.py @@ -1,5 +1,6 @@ from migen.fhdl.structure import * from migen.bank.description import * +from migen.genlib.record import * from miscope.std import * from miscope.trigger import Trigger @@ -12,7 +13,7 @@ class MiLa(Module, AutoCSR): self.with_rle = with_rle self.ports = ports - self.sink = rec_dat(width) + self.sink = Record(dat_layout(width)) trigger = Trigger(width, ports) recorder = Recorder(width, depth) @@ -20,7 +21,7 @@ class MiLa(Module, AutoCSR): self.submodules.trigger = trigger self.submodules.recorder = recorder - sink_d = rec_dat(width) + sink_d = Record(dat_layout(width)) self.sync += sink_d.eq(self.sink) self.comb += [ diff --git a/miscope/std.py b/miscope/std.py index 9d940e67..d7ffc7e3 100644 --- a/miscope/std.py +++ b/miscope/std.py @@ -1,23 +1,13 @@ from migen.genlib.record import * -def rec_dat(width): - layout = [ - ("stb", 1, DIR_M_TO_S), - ("dat", width, DIR_M_TO_S) - ] - return Record(layout) +def dat_layout(dw): + return [ + ("stb", 1, DIR_M_TO_S), + ("dat", dw, DIR_M_TO_S) + ] -def rec_hit(): - layout = [ - ("stb", 1, DIR_M_TO_S), - ("hit", 1, DIR_M_TO_S) - ] - return Record(layout) - -def rec_dat_hit(width): - layout = [ - ("stb", 1, DIR_M_TO_S), - ("hit", 1, DIR_M_TO_S), - ("dat", width, DIR_M_TO_S) - ] - return Record(layout) \ No newline at end of file +def hit_layout(): + return [ + ("stb", 1, DIR_M_TO_S), + ("hit", 1, DIR_M_TO_S) + ] diff --git a/miscope/storage.py b/miscope/storage.py index b05924b2..57860703 100644 --- a/miscope/storage.py +++ b/miscope/storage.py @@ -2,6 +2,7 @@ from migen.fhdl.std import * from migen.bank.description import * from migen.genlib.fifo import SyncFIFOBuffered as SyncFIFO from migen.genlib.fsm import FSM, NextState +from migen.genlib.record import * from miscope.std import * @@ -10,8 +11,8 @@ class RunLengthEncoder(Module, AutoCSR): self.width = width self.length = length - self.sink = rec_dat(width) - self.source = rec_dat(width) + self.sink = Record(dat_layout(width)) + self.source = Record(dat_layout(width)) self._r_enable = CSRStorage() @@ -19,7 +20,7 @@ class RunLengthEncoder(Module, AutoCSR): enable = self._r_enable.storage - sink_d = rec_dat(width) + sink_d = Record(dat_layout(width)) self.sync += If(self.sink.stb, sink_d.eq(self.sink)) cnt = Signal(max=length) @@ -61,8 +62,8 @@ class Recorder(Module, AutoCSR): def __init__(self, width, depth): self.width = width - self.trig_sink = rec_hit() - self.dat_sink = rec_dat(width) + self.trig_sink = Record(hit_layout()) + self.dat_sink = Record(dat_layout(width)) self._r_trigger = CSR() self._r_length = CSRStorage(bits_for(depth)) diff --git a/miscope/trigger.py b/miscope/trigger.py index b7295608..d51eea21 100644 --- a/miscope/trigger.py +++ b/miscope/trigger.py @@ -1,6 +1,7 @@ from migen.fhdl.std import * from migen.fhdl.specials import Memory from migen.bank.description import * +from migen.genlib.record import * from miscope.std import * @@ -8,8 +9,8 @@ class Term(Module, AutoCSR): def __init__(self, width): self.width = width - self.sink = rec_dat(width) - self.source = rec_hit() + self.sink = Record(dat_layout(width)) + self.source = Record(hit_layout()) self._r_trig = CSRStorage(width) self._r_mask = CSRStorage(width) @@ -21,7 +22,7 @@ class Term(Module, AutoCSR): dat = self.sink.dat hit = self.source.hit - self.comb +=[ + self.comb += [ hit.eq((dat & mask) == trig), self.source.stb.eq(self.sink.stb) ] @@ -30,8 +31,8 @@ class RangeDetector(Module, AutoCSR): def __init__(self, width): self.width = width - self.sink = rec_dat(width) - self.source = rec_hit() + self.sink = Record(dat_layout(width)) + self.source = Record(hit_layout()) self._r_low = CSRStorage(width) self._r_high = CSRStorage(width) @@ -43,18 +44,17 @@ class RangeDetector(Module, AutoCSR): dat = self.sink.dat hit = self.source.hit - self.comb +=[ + self.comb += [ hit.eq((dat >= low) & (dat <= high)), self.source.stb.eq(self.sink.stb) ] - class EdgeDetector(Module, AutoCSR): def __init__(self, width): self.width = width - self.sink = rec_dat(width) - self.source = rec_hit() + self.sink = Record(dat_layout(width)) + self.source = Record(hit_layout()) self._r_rising_mask = CSRStorage(width) self._r_falling_mask = CSRStorage(width) @@ -75,7 +75,7 @@ class EdgeDetector(Module, AutoCSR): self.sync += dat_d.eq(dat) - self.comb +=[ + self.comb += [ rising_hit.eq(rising_mask & dat & ~dat_d), falling_hit.eq(rising_mask & ~dat & dat_d), both_hit.eq((both_mask & dat) != (both_mask & dat_d)), @@ -85,9 +85,9 @@ class EdgeDetector(Module, AutoCSR): class Sum(Module, AutoCSR): def __init__(self, ports=4): - - self.sinks = [rec_hit() for p in range(ports)] - self.source = rec_hit() + + self.sinks = [Record(hit_layout()) for p in range(ports)] + self.source = Record(hit_layout()) self._r_prog_we = CSRStorage() self._r_prog_adr = CSRStorage(ports) #FIXME @@ -102,7 +102,7 @@ class Sum(Module, AutoCSR): ### # Lut prog - self.comb +=[ + self.comb += [ prog_port.we.eq(self._r_prog_we.storage), prog_port.adr.eq(self._r_prog_adr.storage), prog_port.dat_w.eq(self._r_prog_dat.storage) @@ -113,7 +113,7 @@ class Sum(Module, AutoCSR): self.comb += lut_port.adr[i].eq(sink.hit) # Drive source - self.comb +=[ + self.comb += [ self.source.stb.eq(optree("&", [sink.stb for sink in self.sinks])), self.source.hit.eq(lut_port.dat_r), ] @@ -123,22 +123,18 @@ class Trigger(Module, AutoCSR): def __init__(self, width, ports): self.width = width self.ports = ports - - self.submodules.sum = Sum(len(ports)) - # FIXME : when self.submodules += is used, - # get_csrs() is not called + self.submodules.sum = Sum(len(ports)) for i, port in enumerate(ports): - tmp = "self.submodules.port"+str(i)+" = port" - exec(tmp) + setattr(self.submodules, "port"+str(i), port) - self.sink = rec_dat(width) + self.sink = Record(dat_layout(width)) self.source = self.sum.source - self.busy = Signal() ### + for i, port in enumerate(ports): - self.comb +=[ + self.comb += [ self.sink.connect(port.sink), port.source.connect(self.sum.sinks[i]) - ] \ No newline at end of file + ] diff --git a/miscope/uart2wishbone.py b/miscope/uart2wishbone.py index b6665e87..185232e5 100644 --- a/miscope/uart2wishbone.py +++ b/miscope/uart2wishbone.py @@ -7,36 +7,28 @@ from migen.genlib.misc import split, displacer, chooser from migen.bank.description import * from migen.bus import wishbone - -# Todo -# ---- -# - implement timeout in fsm to prevent deadlocks - -def rec_rx(): - layout = [ +def rx_layout(): + return [ ("stb", 1, DIR_M_TO_S), ("dat", 8, DIR_M_TO_S) - ] - return Record(layout) + ] -def rec_tx(): - layout = [ +def tx_layout(): + return [ ("stb", 1, DIR_M_TO_S), ("ack", 1, DIR_S_TO_M), ("dat", 8, DIR_M_TO_S) - ] - return Record(layout) + ] class UART(Module): def __init__(self, pads, clk_freq, baud=115200): - - self.rx = rec_rx() - self.tx = rec_tx() + self.rx = Record(rx_layout()) + self.tx = Record(tx_layout()) self.divisor = Signal(16, reset=int(clk_freq/baud/16)) pads.tx.reset = 1 - + ### enable16 = Signal() @@ -47,7 +39,7 @@ class UART(Module): If(enable16, enable16_counter.eq(self.divisor - 1)) ] - + # TX tx_reg = Signal(8) tx_bitcount = Signal(4) @@ -81,7 +73,7 @@ class UART(Module): ) ) ] - + # RX rx = Signal() self.specials += MultiReg(pads.rx, rx, "sys") @@ -157,7 +149,6 @@ class UARTMux(Module): pads_tx = [self.pads[i].tx for i in range(nb)] self.comb += chooser(Cat(pads_tx), self.sel, pads.tx, n=nb) - class UART2Wishbone(Module, AutoCSR): WRITE_CMD = 0x01 READ_CMD = 0x02 @@ -294,4 +285,3 @@ class UART2Wishbone(Module, AutoCSR): ).Elif(fsm.ongoing("READ_DATA") & self.wishbone.stb & self.wishbone.ack, data.eq(self.wishbone.dat_r) ) - -- 2.30.2