new action syntax for make.py + support xc3sprog
authorSebastien Bourdeauducq <sb@m-labs.hk>
Sat, 15 Feb 2014 13:01:50 +0000 (14:01 +0100)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sat, 15 Feb 2014 13:01:50 +0000 (14:01 +0100)
jtag.py [deleted file]
make.py
programmer.py [new file with mode: 0644]
software/bios/Makefile

diff --git a/jtag.py b/jtag.py
deleted file mode 100644 (file)
index 853cf71..0000000
--- a/jtag.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import subprocess
-
-cables = {
-       "mixxeo":               "milkymist",
-       "m1":                   "milkymist",
-       "papilio_pro":  "Flyswatter"
-}
-
-def load(platform_name, bitstream):
-       cmds = """cable {cable}
-detect
-pld load {bitstream}
-quit
-""".format(cable=cables[platform_name], bitstream=bitstream)
-       process = subprocess.Popen("jtag", stdin=subprocess.PIPE)
-       process.stdin.write(cmds.encode("ASCII"))
-       process.communicate()
-
-def flash(bitstream):
-       subprocess.call(["m1nor-ng", bitstream])
diff --git a/make.py b/make.py
index 1c030b66c9f4d6f9aac286e064fdbd261b67115b..3932860d1f535eb36c5f9a25016a9fd787dba6d3 100755 (executable)
--- a/make.py
+++ b/make.py
@@ -8,10 +8,30 @@ from migen.fhdl import simplify
 
 from misoclib.gensoc import cpuif
 from misoclib.s6ddrphy import initsequence
-import jtag
+import programmer
 
 def _get_args():
-       parser = argparse.ArgumentParser(description="MiSoC - a high performance and small footprint SoC based on Migen.")
+       parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
+               description="""\
+MiSoC - a high performance and small footprint SoC based on Migen.
+
+This program builds and/or loads MiSoC components.
+One or several actions can be specified:
+
+build-bitstream build FPGA bitstream. Implies build-bios on targets with
+                integrated BIOS.
+build-headers   build software header files with CSR/IRQ/SDRAM_PHY definitions.
+build-csr-csv   save CSR map into CSV file.
+build-bios      build BIOS. Implies build-header.
+
+load-bitstream  load bitstream into volatile storage.
+flash-bitstream load bitstream into non-volatile storage.
+flash-bios      load BIOS into non-volatile storage.
+
+all             build-bitstream, build-bios, flash-bitstream, flash-bios.
+
+Load/flash actions use the existing outputs, and do not trigger new builds.
+""")
 
        parser.add_argument("-p", "--platform", default="mixxeo", help="platform to build for")
        parser.add_argument("-t", "--target", default="mlabs_video", help="SoC type to build")
@@ -22,12 +42,8 @@ def _get_args():
 
        parser.add_argument("-d", "--decorate", default=[], action="append", help="apply simplification decorator to top-level")
        parser.add_argument("-Ob", "--build-option", default=[], nargs=2, action="append", help="set build option")
-       parser.add_argument("-B", "--no-bitstream", default=False, action="store_true", help="do not build bitstream file")
-       parser.add_argument("-H", "--no-header", default=False, action="store_true", help="do not build C header files with CSR/IRQ/SDRAM_PHY definitions")
-       parser.add_argument("-c", "--csr-csv", default="", help="save CSR map into CSV file")
 
-       parser.add_argument("-l", "--load", default=False, action="store_true", help="load bitstream to FPGA volatile memory")
-       parser.add_argument("-f", "--flash", default=False, action="store_true", help="load bitstream to flash")
+       parser.add_argument("action", nargs="+", help="specify an action")
 
        return parser.parse_args()
 
@@ -44,9 +60,10 @@ def _misoc_import(default, external, name):
        else:
                return importlib.import_module(default + "." + name)
 
-def main():
+if __name__ == "__main__":
        args = _get_args()
 
+       # create top-level SoC object
        platform_module = _misoc_import("mibuild.platforms", args.external_platform, args.platform)
        target_module = _misoc_import("targets", args.external_target, args.target)
        platform = platform_module.Platform()
@@ -57,10 +74,33 @@ def main():
        build_name = top_class.__name__.lower() + "-" + args.platform
        top_kwargs = dict((k, autotype(v)) for k, v in args.target_option)
        soc = top_class(platform, **top_kwargs)
-
        soc.finalize()
 
-       if not args.no_header:
+       # decode actions
+       action_list = ["build-bitstream", "build-headers", "build-csr-csv", "build-bios",
+               "load-bitstream", "flash-bitstream", "flash-bios", "all"]
+       actions = {k: False for k in action_list}
+       for action in args.action:
+               if action in actions:
+                       actions[action] = True
+               else:
+                       print("Unknown action: "+action+". Valid actions are:")
+                       for a in action_list:
+                               print("  "+a)
+                       sys.exit(1)
+
+       # dependencies
+       if actions["all"]:
+               actions["build-bitstream"] = True
+               actions["build-bios"] = True
+               actions["flash-bitstream"] = True
+               actions["flash-bios"] = True
+       if actions["build-bitstream"] and hasattr(soc, "init_bios_memory"):
+               actions["build-bios"] = True
+       if actions["build-bios"]:
+               actions["build-headers"] = True
+
+       if actions["build-headers"]:
                boilerplate = """/*
  * Platform: {}
  * Target: {}
@@ -75,38 +115,44 @@ def main():
                if hasattr(soc, "ddrphy"):
                        sdram_phy_header = initsequence.get_sdram_phy_header(soc.ddrphy)
                        write_to_file("software/include/generated/sdram_phy.h", boilerplate + sdram_phy_header)
-       if args.csr_csv:
+
+       if actions["build-csr-csv"]:
                csr_csv = cpuif.get_csr_csv(soc.csr_base, soc.csrbankarray)
                write_to_file(args.csr_csv, csr_csv)
 
-       if hasattr(soc, "init_bios_memory"):
+       if actions["build-bios"]:
                ret = subprocess.call(["make", "-C", "software/bios"])
                if ret:
                        raise OSError("BIOS build failed")
-               bios_file = open("software/bios/bios.bin", "rb")
-               bios_data = []
-               while True:
-                       w = bios_file.read(4)
-                       if not w:
-                               break
-                       bios_data.append(struct.unpack(">I", w)[0])
-               bios_file.close()
-               soc.init_bios_memory(bios_data)
 
-       for decorator in args.decorate:
-               soc = getattr(simplify, decorator)(soc)
+       if hasattr(soc, "init_bios_memory"):
+               with open("software/bios/bios.bin", "rb") as bios_file:
+                       bios_data = []
+                       while True:
+                               w = bios_file.read(4)
+                               if not w:
+                                       break
+                               bios_data.append(struct.unpack(">I", w)[0])
+               soc.init_bios_memory(bios_data)
 
-       if not args.no_bitstream:
+       if actions["build-bitstream"]:
+               for decorator in args.decorate:
+                       soc = getattr(simplify, decorator)(soc)
                build_kwargs = dict((k, autotype(v)) for k, v in args.build_option)
                platform.build(soc, build_name=build_name, **build_kwargs)
-               subprocess.call(["tools/byteswap",
-                       "build/" + build_name + ".bin",
-                       "build/" + build_name + ".fpg"])
-
-       if args.load:
-               jtag.load(platform.name, "build/" + build_name + ".bit")
-       if args.flash:
-               jtag.flash("build/" + build_name + ".fpg")
 
-if __name__ == "__main__":
-       main()
+       if actions["load-bitstream"] or actions["flash-bitstream"] or actions["flash-bios"]:
+               prog = programmer.create_programmer(platform.name, None)
+               if actions["load-bitstream"]:
+                       prog.load_bitstream("build/" + build_name + ".bit")
+               if actions["flash-bitstream"]:
+                       if prog.needs_bitreverse:
+                               flashbit = "build/" + build_name + ".fpg"
+                               subprocess.call(["tools/byteswap",
+                                       "build/" + build_name + ".bin",
+                                       flashbit])
+                       else:
+                               flashbit = "build/" + build_name + ".bin"
+                       prog.flash(0, flashbit)
+               if actions["flash-bios"]:
+                       prog.flash(soc.cpu_reset_address, "software/bios/bios.bin")
diff --git a/programmer.py b/programmer.py
new file mode 100644 (file)
index 0000000..7615fde
--- /dev/null
@@ -0,0 +1,65 @@
+import subprocess
+import os
+
+class Programmer:
+       def __init__(self, platform_name, flash_proxy_dir):
+               self.platform_name = platform_name
+               self.flash_proxy_dir = flash_proxy_dir
+
+       def find_flash_proxy(self, name):
+               if self.flash_proxy_dir is not None:
+                       search_dirs = [self.flash_proxy_dir]
+               else:
+                       search_dirs = ["~/.mlabs", "/usr/local/share/mlabs", "/usr/share/mlabs"]
+               for d in search_dirs:
+                       fulldir = os.path.abspath(os.path.expanduser(d))
+                       fullname = os.path.join(fulldir, name)
+                       if os.path.exists(fullname):
+                               return fullname
+               raise OSError("Failed to find flash proxy bitstream")
+
+def _run_urjtag(cmds):
+       with subprocess.Popen("jtag", stdin=subprocess.PIPE) as process:
+               process.stdin.write(cmds.encode("ASCII"))
+               process.communicate()
+
+class UrJTAG(Programmer):
+       needs_bitreverse = True
+
+       def load_bitstream(self, bitstream_file):
+               cmds = """cable milkymist
+detect
+pld load {bitstream}
+quit
+""".format(bitstream=bitstream_file)
+               _run_urjtag(cmds)
+
+       def flash(self, address, data_file):
+               flash_proxy = self.find_flash_proxy("fjmem-" + self.platform_name + ".bit")
+               cmds = """cable milkymist
+detect
+pld load "{flash_proxy}"
+initbus fjmem opcode=000010
+frequency 6000000
+detectflash 0
+endian big
+flashmem "{address}" "{data_file}" noverify
+""".format(flash_proxy=flash_proxy, address=address, data_file=data_file)
+               _run_urjtag(cmds)
+
+class XC3SProg(Programmer):
+       needs_bitreverse = False
+
+       def load_bitstream(self, bitstream_file):
+               subprocess.call(["xc3sprog", "-c", "papilio", bitstream_file])
+
+       def flash(self, address, data_file):
+               flash_proxy = self.find_flash_proxy("bscan_spi_lx9_papilio.bit")
+               subprocess.call(["xc3sprog", "-c", "papilio", "-I"+flash_proxy, "{}:w:0x{:x}:BIN".format(data_file, address)])
+
+def create_programmer(platform_name, *args, **kwargs):
+       return {
+               "mixxeo":               UrJTAG,
+               "m1":                   UrJTAG,
+               "papilio_pro":  XC3SProg
+       }[platform_name](platform_name, *args, **kwargs)
index f6d45b87a719e767759eb3d63fbe2c92121a1af2..719314bd1e76b7c92e14a065c82412c55100f1e0 100644 (file)
@@ -40,10 +40,7 @@ libs:
        $(MAKE) -C $(MSCDIR)/software/libbase
        $(MAKE) -C $(MSCDIR)/software/libnet
 
-flash: bios.bin
-       m1nor-ng bios.bin
-
 clean:
        $(RM) $(OBJECTS) $(OBJECTS:.o=.d) bios.elf bios.bin .*~ *~
 
-.PHONY: all main.o clean libs flash
+.PHONY: all main.o clean libs