cli: new module, for basic design generaton/simulation.
authorwhitequark <cz@m-labs.hk>
Sat, 22 Dec 2018 23:56:02 +0000 (23:56 +0000)
committerwhitequark <cz@m-labs.hk>
Sun, 23 Dec 2018 00:06:58 +0000 (00:06 +0000)
examples/alu.py
examples/alu_hier.py
examples/arst.py
examples/cdc.py
examples/ctr.py
examples/gpio.py
examples/inst.py
examples/mem.py
examples/pmux.py
nmigen/cli.py [new file with mode: 0644]

index 4b051c6be245c04935d8503476205903364d1183..f75bd07f4021d92932780980c08357ca61dae71f 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog
+from nmigen.cli import main
 
 
 class ALU:
@@ -23,7 +23,6 @@ class ALU:
         return m.lower(platform)
 
 
-alu  = ALU(width=16)
-frag = alu.get_fragment(platform=None)
-# print(rtlil.convert(frag, ports=[alu.sel, alu.a, alu.b, alu.o, alu.co]))
-print(verilog.convert(frag, ports=[alu.sel, alu.a, alu.b, alu.o, alu.co]))
+if __name__ == "__main__":
+    alu = ALU(width=16)
+    main(alu, ports=[alu.sel, alu.a, alu.b, alu.o, alu.co])
index 8551d38fea0160eca1696623b9033cbb87be2dec..cd31ce93ae47ef0d97b948d7e7b156ebf16b94ed 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog
+from nmigen.cli import main
 
 
 class Adder:
@@ -53,7 +53,6 @@ class ALU:
         return m.lower(platform)
 
 
-alu  = ALU(width=16)
-frag = alu.get_fragment(platform=None)
-# print(rtlil.convert(frag, ports=[alu.op, alu.a, alu.b, alu.o]))
-print(verilog.convert(frag, ports=[alu.op, alu.a, alu.b, alu.o]))
+if __name__ == "__main__":
+    alu = ALU(width=16)
+    main(alu, ports=[alu.op, alu.a, alu.b, alu.o])
index e99fc8d0bb938c07b98a171618ef094110b210a3..4cbdb148b6d440acffc1a74cc1302407cbdea1f4 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog
+from nmigen.cli import main
 
 
 class ClockDivisor:
@@ -14,8 +14,8 @@ class ClockDivisor:
         return m.lower(platform)
 
 
-ctr  = ClockDivisor(factor=16)
-frag = ctr.get_fragment(platform=None)
-frag.add_domains(ClockDomain("sync", async_reset=True))
-# print(rtlil.convert(frag, ports=[ctr.o]))
-print(verilog.convert(frag, ports=[ctr.o]))
+if __name__ == "__main__":
+    ctr  = ClockDivisor(factor=16)
+    frag = ctr.get_fragment(platform=None)
+    frag.add_domains(ClockDomain("sync", async_reset=True))
+    main(frag, ports=[ctr.o])
index 7d2486df347ef6ca51048b4c98ecaf5b00804db5..80b335e6bfc20862f5e5f35ea00c6ad0adf536bf 100644 (file)
@@ -1,10 +1,10 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog
+from nmigen.cli import main
 
 
 i, o = Signal(name="i"), Signal(name="o")
 m = Module()
 m.submodules += MultiReg(i, o)
-frag = m.lower(platform=None)
-# print(rtlil.convert(frag, ports=[i, o]))
-print(verilog.convert(frag, ports=[i, o]))
+
+if __name__ == "__main__":
+    main(m.lower(platform=None), ports=[i, o])
index be1bb0958602e7cf8725a1f2b4a22220316642ab..f08bd04625b27c53e4d614e5dc71ecb1fda5d9f2 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog, pysim
+from nmigen.cli import main, pysim
 
 
 class Counter:
@@ -14,13 +14,6 @@ class Counter:
         return m.lower(platform)
 
 
-ctr  = Counter(width=16)
-frag = ctr.get_fragment(platform=None)
-
-# print(rtlil.convert(frag, ports=[ctr.o]))
-print(verilog.convert(frag, ports=[ctr.o]))
-
-with pysim.Simulator(frag,
-        vcd_file=open("ctr.vcd", "w")) as sim:
-    sim.add_clock(1e-6)
-    sim.run_until(100e-6, run_passive=True)
+ctr = Counter(width=16)
+if __name__ == "__main__":
+    main(ctr, ports=[ctr.o])
index 557a85205c3f9483bd15d676bcaaf4598b260be5..06caab169088899e6135999c067f38947dbfc35c 100644 (file)
@@ -1,6 +1,6 @@
 from types import SimpleNamespace
 from nmigen import *
-from nmigen.back import rtlil, verilog, pysim
+from nmigen.cli import main
 
 
 class GPIO:
@@ -16,16 +16,14 @@ class GPIO:
         return m.lower(platform)
 
 
-# TODO: use Record
-bus = SimpleNamespace(
-    adr=Signal(max=8),
-    dat_r=Signal(),
-    dat_w=Signal(),
-    we=Signal()
-)
-pins = Signal(8)
-gpio = GPIO(Array(pins), bus)
-frag = gpio.get_fragment(platform=None)
-
-# print(rtlil.convert(frag, ports=[pins, bus.adr, bus.dat_r, bus.dat_w, bus.we]))
-print(verilog.convert(frag, ports=[pins, bus.adr, bus.dat_r, bus.dat_w, bus.we]))
+if __name__ == "__main__":
+    # TODO: use Record
+    bus = SimpleNamespace(
+        adr  =Signal(name="adr", max=8),
+        dat_r=Signal(name="dat_r"),
+        dat_w=Signal(name="dat_w"),
+        we   =Signal(name="we"),
+    )
+    pins = Signal(8)
+    gpio = GPIO(Array(pins), bus)
+    main(gpio, ports=[pins, bus.adr, bus.dat_r, bus.dat_w, bus.we])
index 5bfdaaa552a5b5549ec0b44ed034fa910e325ec9..28052f7d6a62d0bd5919af5885f5c9251d1427da 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog
+from nmigen.cli import main
 
 
 class System:
@@ -11,7 +11,7 @@ class System:
 
     def get_fragment(self, platform):
         m = Module()
-        m.submodules += Instance("CPU",
+        m.submodules.cpu = Instance("CPU",
             p_RESET_ADDR=0xfff0,
             i_d_adr  =self.adr,
             i_d_dat_r=self.dat_r,
@@ -21,7 +21,6 @@ class System:
         return m.lower(platform)
 
 
-sys  = System()
-frag = sys.get_fragment(platform=None)
-# print(rtlil.convert(frag, ports=[sys.adr, sys.dat_r, sys.dat_w, sys.we]))
-print(verilog.convert(frag, ports=[sys.adr, sys.dat_r, sys.dat_w, sys.we]))
+if __name__ == "__main__":
+    sys = System()
+    main(sys, ports=[sys.adr, sys.dat_r, sys.dat_w, sys.we])
index 1893d90a08f1b4cb2321f3e1bacd3cbe2ecd7a41..4771eed3507d241bddfc5ec227a84f8abdeefc7f 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog
+from nmigen.cli import main
 
 
 class RegisterFile:
@@ -24,7 +24,6 @@ class RegisterFile:
         return m.lower(platform)
 
 
-rf   = RegisterFile()
-frag = rf.get_fragment(platform=None)
-# print(rtlil.convert(frag, ports=[rf.adr, rf.dat_r, rf.dat_w, rf.we]))
-print(verilog.convert(frag, ports=[rf.adr, rf.dat_r, rf.dat_w, rf.we]))
+if __name__ == "__main__":
+    rf = RegisterFile()
+    main(rf, ports=[rf.adr, rf.dat_r, rf.dat_w, rf.we])
index 27ec33fa2db163f8c287a312f2045a67ad811792..2d108d60bfc996c5dde3a5525fb6d16f907714e7 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import *
-from nmigen.back import rtlil, verilog
+from nmigen.cli import main
 
 
 class ParMux:
@@ -24,7 +24,6 @@ class ParMux:
         return m.lower(platform)
 
 
-pmux = ParMux(width=16)
-frag = pmux.get_fragment(platform=None)
-# print(rtlil.convert(frag, ports=[pmux.s, pmux.a, pmux.b, pmux.c, pmux.o]))
-print(verilog.convert(frag, ports=[pmux.s, pmux.a, pmux.b, pmux.c, pmux.o]))
+if __name__ == "__main__":
+    pmux = ParMux(width=16)
+    main(pmux, ports=[pmux.s, pmux.a, pmux.b, pmux.c, pmux.o])
diff --git a/nmigen/cli.py b/nmigen/cli.py
new file mode 100644 (file)
index 0000000..c28e296
--- /dev/null
@@ -0,0 +1,65 @@
+import argparse
+
+from .back import rtlil, verilog, pysim
+
+
+__all__ = ["main"]
+
+
+def main_parser(parser=None):
+    if parser is None:
+        parser = argparse.ArgumentParser()
+
+    p_action = parser.add_subparsers(dest="action")
+
+    p_generate = p_action.add_parser("generate",
+        help="generate RTLIL or Verilog from the design")
+    p_generate.add_argument("-t", "--type", dest="generate_type",
+        metavar="LANGUAGE", choices=["il", "v"], default="v",
+        help="generate LANGUAGE (il for RTLIL, v for Verilog; default: %(default)s)")
+    p_generate.add_argument("generate_file",
+        metavar="FILE", type=argparse.FileType("w"), nargs="?",
+        help="write generated code to FILE")
+
+    p_simulate = p_action.add_parser(
+        "simulate", help="simulate the design")
+    p_simulate.add_argument("-v", "--vcd-file",
+        metavar="VCD-FILE", type=argparse.FileType("w"),
+        help="write execution trace to VCD-FILE")
+    p_simulate.add_argument("-w", "--gtkw-file",
+        metavar="GTKW-FILE", type=argparse.FileType("w"),
+        help="write GTKWave configuration to GTKW-FILE")
+    p_simulate.add_argument("-p", "--period", dest="sync_period",
+        metavar="TIME", type=float, default=1e-6,
+        help="set 'sync' clock domain period to TIME (default: %(default)s)")
+    p_simulate.add_argument("-c", "--clocks", dest="sync_clocks",
+        metavar="COUNT", type=int, required=True,
+        help="simulate for COUNT 'sync' clock periods")
+
+    return parser
+
+
+def main_runner(args, design, platform=None, name="top", ports=()):
+    if args.action == "generate":
+        fragment = design.get_fragment(platform=platform)
+        if args.generate_type == "il":
+            output = rtlil.convert(fragment, name=name, ports=ports)
+        if args.generate_type == "v":
+            output = verilog.convert(fragment, name=name, ports=ports)
+        if args.generate_file:
+            args.generate_file.write(output)
+        else:
+            print(output)
+
+    if args.action == "simulate":
+        fragment = design.get_fragment(platform=platform)
+        with pysim.Simulator(fragment,
+                vcd_file=args.vcd_file,
+                gtkw_file=args.gtkw_file,
+                traces=ports) as sim:
+            sim.add_clock(args.sync_period)
+            sim.run_until(args.sync_period * args.sync_clocks, run_passive=True)
+
+
+def main(*args, **kwargs):
+    main_runner(main_parser().parse_args(), *args, **kwargs)