from mibuild.tools import write_to_file
-from milkymist import cif
+from milkymist import cpuif
+from milkymist.s6ddrphy import initsequence
import top, jtag
-def build(platform_name, build_bitstream, build_header, *soc_args, **soc_kwargs):
+def build(platform_name, build_bitstream, build_header, csr_csv_filename, *soc_args, **soc_kwargs):
platform_module = importlib.import_module("mibuild.platforms."+platform_name)
platform = platform_module.Platform()
soc = top.SoC(platform, platform_name, *soc_args, **soc_kwargs)
else:
soc.finalize()
if build_header:
- csr_header = cif.get_csr_header(soc.csr_base, soc.csrbankarray, soc.interrupt_map)
+ csr_header = cpuif.get_csr_header(soc.csr_base, soc.csrbankarray, soc.interrupt_map)
write_to_file("software/include/hw/csr.h", csr_header)
- sdram_phy_header = cif.get_sdram_phy_header(soc.ddrphy)
+ sdram_phy_header = initsequence.get_sdram_phy_header(soc.ddrphy)
write_to_file("software/include/hw/sdram_phy.h", sdram_phy_header)
-
+ if csr_csv_filename:
+ csr_csv = cpuif.get_csr_csv(soc.csr_base, soc.csrbankarray)
+ write_to_file(csr_csv_filename, csr_csv)
def main():
parser = argparse.ArgumentParser(description="milkymist-ng - a high performance SoC built on Migen technology.")
parser.add_argument("-p", "--platform", default="mixxeo", help="platform to build for")
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 defs")
+ parser.add_argument("-c", "--csr-csv", default="", help="save CSR map in CSV file")
parser.add_argument("-l", "--load", default=False, action="store_true", help="load bitstream to SRAM")
parser.add_argument("-f", "--flash", default=False, action="store_true", help="load bitstream to flash")
parser.add_argument("-m", "--with-memtest", default=False, action="store_true", help="include memtest cores")
args = parser.parse_args()
- build(args.platform, not args.no_bitstream, not args.no_header, args.with_memtest)
+ build(args.platform, not args.no_bitstream, not args.no_header, args.csr_csv, args.with_memtest)
if args.load:
jtag.load("build/soc-"+args.platform+".bit")
if args.flash:
+++ /dev/null
-from operator import itemgetter
-import re
-
-from migen.fhdl.std import *
-from migen.bank.description import CSRStatus
-
-def get_macros(filename):
- f = open(filename, "r")
- r = {}
- for line in f:
- match = re.match("\w*#define\s+(\w+)\s+(.*)", line, re.IGNORECASE)
- if match:
- r[match.group(1)] = match.group(2)
- return r
-
-def _get_rw_functions(reg_name, reg_base, size, read_only):
- r = ""
- if size > 8:
- raise NotImplementedError("Register too large")
- elif size > 4:
- ctype = "unsigned long long int"
- elif size > 2:
- ctype = "unsigned int"
- elif size > 1:
- ctype = "unsigned short int"
- else:
- ctype = "unsigned char"
-
- r += "static inline "+ctype+" "+reg_name+"_read(void) {\n"
- if size > 1:
- r += "\t"+ctype+" r = MMPTR("+hex(reg_base)+");\n"
- for byte in range(1, size):
- r += "\tr <<= 8;\n\tr |= MMPTR("+hex(reg_base+4*byte)+");\n"
- r += "\treturn r;\n}\n"
- else:
- r += "\treturn MMPTR("+hex(reg_base)+");\n}\n"
-
- if not read_only:
- r += "static inline void "+reg_name+"_write("+ctype+" value) {\n"
- for byte in range(size):
- shift = (size-byte-1)*8
- if shift:
- value_shifted = "value >> "+str(shift)
- else:
- value_shifted = "value"
- r += "\tMMPTR("+hex(reg_base+4*byte)+") = "+value_shifted+";\n"
- r += "}\n"
- return r
-
-def get_csr_header(csr_base, bank_array, interrupt_map):
- r = "#ifndef __HW_CSR_H\n#define __HW_CSR_H\n#include <hw/common.h>\n"
- for name, csrs, mapaddr, rmap in bank_array.banks:
- r += "\n/* "+name+" */\n"
- reg_base = csr_base + 0x800*mapaddr
- r += "#define "+name.upper()+"_BASE "+hex(reg_base)+"\n"
- for csr in csrs:
- nr = (csr.size + 7)//8
- r += _get_rw_functions(name + "_" + csr.name, reg_base, nr, isinstance(csr, CSRStatus))
- reg_base += 4*nr
- try:
- interrupt_nr = interrupt_map[name]
- except KeyError:
- pass
- else:
- r += "#define "+name.upper()+"_INTERRUPT "+str(interrupt_nr)+"\n"
- r += "\n#endif\n"
- return r
-
-def get_sdram_phy_header(sdram_phy):
- if sdram_phy.phy_settings.memtype not in ["SDR", "DDR", "LPDDR", "DDR2"]:
- raise NotImplementedError("The SDRAM PHY header generator only supports SDR, DDR, LPDDR and DDR2")
-
- r = "#ifndef __HW_SDRAM_PHY_H\n#define __HW_SDRAM_PHY_H\n"
- r += "#include <hw/common.h>\n#include <hw/csr.h>\n#include <hw/flags.h>\n\n"
-
- r += "static void cdelay(int i);\n"
-
- #
- # commands_px functions
- #
- for n in range(sdram_phy.phy_settings.nphases):
- r += """
-static void command_p{n}(int cmd)
-{{
- dfii_pi{n}_command_write(cmd);
- dfii_pi{n}_command_issue_write(1);
-}}""".format(n=str(n))
- r += "\n\n"
-
- #
- # rd/wr access macros
- #
- r += """
-#define dfii_pird_address_write(X) dfii_pi{rdphase}_address_write(X)
-#define dfii_piwr_address_write(X) dfii_pi{wrphase}_address_write(X)
-
-#define dfii_pird_baddress_write(X) dfii_pi{rdphase}_baddress_write(X)
-#define dfii_piwr_baddress_write(X) dfii_pi{wrphase}_baddress_write(X)
-
-#define command_prd(X) command_p{rdphase}(X)
-#define command_pwr(X) command_p{wrphase}(X)
-""".format(rdphase=str(sdram_phy.phy_settings.rdphase), wrphase=str(sdram_phy.phy_settings.wrphase))
- r +="\n"
-
- #
- # init sequence
- #
- cmds = {
- "PRECHARGE_ALL" : "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
- "MODE_REGISTER" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
- "AUTO_REFRESH" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
- "CKE" : "DFII_CONTROL_CKE"
- }
-
- def gen_cmd(comment, a, ba, cmd, delay):
- r = "\t/* {0} */\n".format(comment)
- r += "\tdfii_pi0_address_write({0:#x});\n".format(a)
- r += "\tdfii_pi0_baddress_write({0:d});\n".format(ba)
- if "CKE" in cmd:
- r += "\tdfii_control_write({0});\n".format(cmd)
- else:
- r += "\tcommand_p0({0});\n".format(cmd)
- r += "\tcdelay({0:d});\n".format(delay)
- r += "\n"
- return r
-
-
- r += "static void init_sequence(void)\n{\n"
-
- cl = sdram_phy.phy_settings.cl
-
- if sdram_phy.phy_settings.memtype == "SDR":
- bl = 1*sdram_phy.phy_settings.nphases
- mr = log2_int(bl) + (cl << 4)
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- elif sdram_phy.phy_settings.memtype == "DDR":
- bl = 2*sdram_phy.phy_settings.nphases
- mr = log2_int(bl) + (cl << 4)
- emr = 0
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- elif sdram_phy.phy_settings.memtype == "LPDDR":
- bl = 2*sdram_phy.phy_settings.nphases
- mr = log2_int(bl) + (cl << 4)
- emr = 0
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- elif sdram_phy.phy_settings.memtype == "DDR2":
- bl = 2*sdram_phy.phy_settings.nphases
- wr = 2
- mr = log2_int(bl) + (cl << 4) + (wr << 9)
- emr = 0
- emr2 = 0
- emr3 = 0
- reset_dll = 1 << 8
- ocd = 7 << 7
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
- ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
- ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200),
- ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
- ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
- ]
-
- for comment, a, ba, cmd, delay in init_sequence:
- r += gen_cmd(comment, a, ba, cmd, delay)
-
- r += "}\n"
- r += "#endif\n"
-
- return r
--- /dev/null
+from migen.bank.description import CSRStatus
+
+def _get_rw_functions(reg_name, reg_base, size, read_only):
+ r = ""
+ if size > 8:
+ raise NotImplementedError("Register too large")
+ elif size > 4:
+ ctype = "unsigned long long int"
+ elif size > 2:
+ ctype = "unsigned int"
+ elif size > 1:
+ ctype = "unsigned short int"
+ else:
+ ctype = "unsigned char"
+
+ r += "static inline "+ctype+" "+reg_name+"_read(void) {\n"
+ if size > 1:
+ r += "\t"+ctype+" r = MMPTR("+hex(reg_base)+");\n"
+ for byte in range(1, size):
+ r += "\tr <<= 8;\n\tr |= MMPTR("+hex(reg_base+4*byte)+");\n"
+ r += "\treturn r;\n}\n"
+ else:
+ r += "\treturn MMPTR("+hex(reg_base)+");\n}\n"
+
+ if not read_only:
+ r += "static inline void "+reg_name+"_write("+ctype+" value) {\n"
+ for byte in range(size):
+ shift = (size-byte-1)*8
+ if shift:
+ value_shifted = "value >> "+str(shift)
+ else:
+ value_shifted = "value"
+ r += "\tMMPTR("+hex(reg_base+4*byte)+") = "+value_shifted+";\n"
+ r += "}\n"
+ return r
+
+def get_csr_header(csr_base, bank_array, interrupt_map):
+ r = "#ifndef __HW_CSR_H\n#define __HW_CSR_H\n#include <hw/common.h>\n"
+ for name, csrs, mapaddr, rmap in bank_array.banks:
+ r += "\n/* "+name+" */\n"
+ reg_base = csr_base + 0x800*mapaddr
+ r += "#define "+name.upper()+"_BASE "+hex(reg_base)+"\n"
+ for csr in csrs:
+ nr = (csr.size + 7)//8
+ r += _get_rw_functions(name + "_" + csr.name, reg_base, nr, isinstance(csr, CSRStatus))
+ reg_base += 4*nr
+ try:
+ interrupt_nr = interrupt_map[name]
+ except KeyError:
+ pass
+ else:
+ r += "#define "+name.upper()+"_INTERRUPT "+str(interrupt_nr)+"\n"
+ r += "\n#endif\n"
+ return r
+
+def get_csr_csv(csr_base, bank_array):
+ r = ""
+ for name, csrs, mapaddr, rmap in bank_array.banks:
+ reg_base = csr_base + 0x800*mapaddr
+ for csr in csrs:
+ nr = (csr.size + 7)//8
+ r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, reg_base, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
+ reg_base += 4*nr
+ return r
--- /dev/null
+from migen.fhdl.std import log2_int
+
+def get_sdram_phy_header(sdram_phy):
+ if sdram_phy.phy_settings.memtype not in ["SDR", "DDR", "LPDDR", "DDR2"]:
+ raise NotImplementedError("The SDRAM PHY header generator only supports SDR, DDR, LPDDR and DDR2")
+
+ r = "#ifndef __HW_SDRAM_PHY_H\n#define __HW_SDRAM_PHY_H\n"
+ r += "#include <hw/common.h>\n#include <hw/csr.h>\n#include <hw/flags.h>\n\n"
+
+ r += "static void cdelay(int i);\n"
+
+ #
+ # commands_px functions
+ #
+ for n in range(sdram_phy.phy_settings.nphases):
+ r += """
+static void command_p{n}(int cmd)
+{{
+ dfii_pi{n}_command_write(cmd);
+ dfii_pi{n}_command_issue_write(1);
+}}""".format(n=str(n))
+ r += "\n\n"
+
+ #
+ # rd/wr access macros
+ #
+ r += """
+#define dfii_pird_address_write(X) dfii_pi{rdphase}_address_write(X)
+#define dfii_piwr_address_write(X) dfii_pi{wrphase}_address_write(X)
+
+#define dfii_pird_baddress_write(X) dfii_pi{rdphase}_baddress_write(X)
+#define dfii_piwr_baddress_write(X) dfii_pi{wrphase}_baddress_write(X)
+
+#define command_prd(X) command_p{rdphase}(X)
+#define command_pwr(X) command_p{wrphase}(X)
+""".format(rdphase=str(sdram_phy.phy_settings.rdphase), wrphase=str(sdram_phy.phy_settings.wrphase))
+ r +="\n"
+
+ #
+ # init sequence
+ #
+ cmds = {
+ "PRECHARGE_ALL" : "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+ "MODE_REGISTER" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+ "AUTO_REFRESH" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
+ "CKE" : "DFII_CONTROL_CKE"
+ }
+
+ def gen_cmd(comment, a, ba, cmd, delay):
+ r = "\t/* {0} */\n".format(comment)
+ r += "\tdfii_pi0_address_write({0:#x});\n".format(a)
+ r += "\tdfii_pi0_baddress_write({0:d});\n".format(ba)
+ if "CKE" in cmd:
+ r += "\tdfii_control_write({0});\n".format(cmd)
+ else:
+ r += "\tcommand_p0({0});\n".format(cmd)
+ r += "\tcdelay({0:d});\n".format(delay)
+ r += "\n"
+ return r
+
+
+ r += "static void init_sequence(void)\n{\n"
+
+ cl = sdram_phy.phy_settings.cl
+
+ if sdram_phy.phy_settings.memtype == "SDR":
+ bl = 1*sdram_phy.phy_settings.nphases
+ mr = log2_int(bl) + (cl << 4)
+ reset_dll = 1 << 8
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+ ]
+
+ elif sdram_phy.phy_settings.memtype == "DDR":
+ bl = 2*sdram_phy.phy_settings.nphases
+ mr = log2_int(bl) + (cl << 4)
+ emr = 0
+ reset_dll = 1 << 8
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+ ]
+
+ elif sdram_phy.phy_settings.memtype == "LPDDR":
+ bl = 2*sdram_phy.phy_settings.nphases
+ mr = log2_int(bl) + (cl << 4)
+ emr = 0
+ reset_dll = 1 << 8
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+ ]
+
+ elif sdram_phy.phy_settings.memtype == "DDR2":
+ bl = 2*sdram_phy.phy_settings.nphases
+ wr = 2
+ mr = log2_int(bl) + (cl << 4) + (wr << 9)
+ emr = 0
+ emr2 = 0
+ emr3 = 0
+ reset_dll = 1 << 8
+ ocd = 7 << 7
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
+ ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
+ ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200),
+ ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
+ ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
+ ]
+
+ for comment, a, ba, cmd, delay in init_sequence:
+ r += gen_cmd(comment, a, ba, cmd, delay)
+
+ r += "}\n"
+ r += "#endif\n"
+
+ return r
from milkymist import mxcrg, lm32, norflash, uart, s6ddrphy, dfii, lasmicon, \
identifier, timer, minimac3, framebuffer, dvisampler, gpio, memtest
-from milkymist.cif import get_macros
-version = get_macros("common/version.h")["VERSION"][1:-1]
+version = "2.0"
clk_freq = (83 + Fraction(1, 3))*1000000
sram_size = 4096 # in bytes