From c06bd2c77d023aab739f056d31fecef0a53de283 Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Sat, 8 May 2021 07:39:13 -0400 Subject: [PATCH] Make the [ID]TLB size configurable from Litex ; expand the DTS to include cache/TLB/topology in CPUs & generate the required information for VexRiscv --- litex/soc/cores/cpu/vexriscv_smp/core.py | 28 ++++++++++++ litex/tools/litex_json2dts.py | 57 +++++++++++++++++++++--- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv_smp/core.py b/litex/soc/cores/cpu/vexriscv_smp/core.py index 3b95b73aa..bdc7476cd 100644 --- a/litex/soc/cores/cpu/vexriscv_smp/core.py +++ b/litex/soc/cores/cpu/vexriscv_smp/core.py @@ -56,6 +56,8 @@ class VexRiscvSMP(CPU): with_fpu = False cpu_per_fpu = 4 with_rvc = False + dtlb_size = 4 + itlb_size = 4 # Command line configuration arguments. @staticmethod @@ -75,6 +77,8 @@ class VexRiscvSMP(CPU): parser.add_argument("--with-fpu" , action="store_true", help="Enable the F32/F64 FPU") parser.add_argument("--cpu-per-fpu" , default="4", help="Maximal ratio between CPU count and FPU count. Will instanciate as many FPU as necessary.") parser.add_argument("--with-rvc" , action="store_true", help="Enable RISC-V compressed instruction support") + parser.add_argument("--dtlb-size", default=4, help="Data TLB size.") + parser.add_argument("--itlb-size", default=4, help="Instruction TLB size.") @staticmethod def args_read(args): @@ -106,6 +110,8 @@ class VexRiscvSMP(CPU): VexRiscvSMP.cpu_per_fpu = args.cpu_per_fpu if(args.with_rvc): VexRiscvSMP.with_rvc = True + if(args.dtlb_size): VexRiscvSMP.dtlb_size = int(args.dtlb_size) + if(args.itlb_size): VexRiscvSMP.itlb_size = int(args.itlb_size) # ABI. @staticmethod @@ -159,6 +165,9 @@ class VexRiscvSMP(CPU): f"Dw{VexRiscvSMP.dcache_width}" \ f"Ds{VexRiscvSMP.dcache_size}" \ f"Dy{VexRiscvSMP.dcache_ways}" \ + "_" \ + f"ITs{VexRiscvSMP.itlb_size}" \ + f"DTs{VexRiscvSMP.dtlb_size}" \ f"{'_'+ldw if not VexRiscvSMP.wishbone_memory else ''}" \ f"{'_Cdma' if VexRiscvSMP.coherent_dma else ''}" \ f"{'_Aes' if VexRiscvSMP.aes_instruction else ''}" \ @@ -250,6 +259,8 @@ class VexRiscvSMP(CPU): gen_args.append(f"--rvc={VexRiscvSMP.with_rvc}") gen_args.append(f"--netlist-name={VexRiscvSMP.cluster_name}") gen_args.append(f"--netlist-directory={vdir}") + gen_args.append(f"--dtlb-size={VexRiscvSMP.dtlb_size}") + gen_args.append(f"--itlb-size={VexRiscvSMP.itlb_size}") cmd = 'cd {path} && sbt "runMain vexriscv.demo.smp.VexRiscvLitexSmpClusterCmdGen {args}"'.format(path=os.path.join(vdir, "ext", "VexRiscv"), args=" ".join(gen_args)) if os.system(cmd) != 0: @@ -361,6 +372,23 @@ class VexRiscvSMP(CPU): # Define number of CPUs soc.add_config("CPU_COUNT", VexRiscvSMP.cpu_count) soc.add_constant("CPU_ISA", VexRiscvSMP.get_arch()) + # constants for cache so we can add them in the DTS + if (VexRiscvSMP.dcache_size > 0): + soc.add_constant("cpu_dcache_size", VexRiscvSMP.dcache_size) + soc.add_constant("cpu_dcache_ways", VexRiscvSMP.dcache_ways) + soc.add_constant("cpu_dcache_block_size", 64) # hardwired? + if (VexRiscvSMP.icache_size > 0): + soc.add_constant("cpu_icache_size", VexRiscvSMP.icache_size) + soc.add_constant("cpu_icache_ways", VexRiscvSMP.icache_ways) + soc.add_constant("cpu_icache_block_size", 64) # hardwired? + # constants for TLB so we can add them in the DTS + # full associative so only the size is described + if (VexRiscvSMP.dtlb_size > 0): + soc.add_constant("cpu_dtlb_size", VexRiscvSMP.dtlb_size) + soc.add_constant("cpu_dtlb_ways", VexRiscvSMP.dtlb_size) + if (VexRiscvSMP.itlb_size > 0): + soc.add_constant("cpu_itlb_size", VexRiscvSMP.itlb_size) + soc.add_constant("cpu_itlb_ways", VexRiscvSMP.itlb_size) # Add PLIC as Bus Slave self.plicbus = plicbus = wishbone.Interface() diff --git a/litex/tools/litex_json2dts.py b/litex/tools/litex_json2dts.py index e5e9d0b40..41d371df4 100755 --- a/litex/tools/litex_json2dts.py +++ b/litex/tools/litex_json2dts.py @@ -61,16 +61,60 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False): # VexRiscv-SMP if cpu_name == "vexriscv smp-linux": + # cache description + cache_desc = "" + if "cpu_dcache_size" in d["constants"]: + cache_desc += """ + d-cache-size = <{d_cache_size}>; + d-cache-sets = <{d_cache_ways}>; + d-cache-block-size = <{d_cache_block_size}>; +""".format(d_cache_size=d["constants"]["cpu_dcache_size"], d_cache_ways=d["constants"]["cpu_dcache_ways"], d_cache_block_size=d["constants"]["cpu_dcache_block_size"]) + if "cpu_icache_size" in d["constants"]: + cache_desc += """ + i-cache-size = <{i_cache_size}>; + i-cache-sets = <{i_cache_ways}>; + i-cache-block-size = <{i_cache_block_size}>; +""".format(i_cache_size=d["constants"]["cpu_icache_size"], i_cache_ways=d["constants"]["cpu_icache_ways"], i_cache_block_size=d["constants"]["cpu_icache_block_size"]) + + # tlb description + tlb_desc = "" + if "cpu_dtlb_size" in d["constants"]: + tlb_desc += """ + d-tlb-size = <{d_tlb_size}>; + d-tlb-sets = <{d_tlb_ways}>; +""".format(d_tlb_size=d["constants"]["cpu_dtlb_size"], d_tlb_ways=d["constants"]["cpu_dtlb_ways"]) + if "cpu_itlb_size" in d["constants"]: + tlb_desc += """ + i-tlb-size = <{i_tlb_size}>; + i-tlb-sets = <{i_tlb_ways}>; +""".format(i_tlb_size=d["constants"]["cpu_itlb_size"], i_tlb_ways=d["constants"]["cpu_itlb_ways"]) + + cpus = range(int(d["constants"]["config_cpu_count"])) + + # topology + cpu_map = "" + if int(d["constants"]["config_cpu_count"]) > 1: + cpu_map += """ + cpu-map { + cluster0 {""" + for cpu in cpus: + cpu_map += """ + core{cpu} {{ + cpu = <&CPU{cpu}>; + }};""".format(cpu=cpu) + cpu_map += """ + }; + };""" + dts += """ cpus {{ #address-cells = <1>; #size-cells = <0>; timebase-frequency = <{sys_clk_freq}>; """.format(sys_clk_freq=d["constants"]["config_clock_frequency"]) - cpus = range(int(d["constants"]["config_cpu_count"])) for cpu in cpus: dts += """ - cpu@{cpu} {{ + CPU{cpu}: cpu@{cpu} {{ device_type = "cpu"; compatible = "riscv"; riscv,isa = "{cpu_isa}"; @@ -78,16 +122,19 @@ def generate_dts(d, initrd_start=None, initrd_size=None, polling=False): reg = <{cpu}>; clock-frequency = <{sys_clk_freq}>; status = "okay"; + {cache_desc} + {tlb_desc} L{irq}: interrupt-controller {{ #interrupt-cells = <0x00000001>; interrupt-controller; compatible = "riscv,cpu-intc"; }}; }}; -""".format(cpu=cpu, irq=cpu, sys_clk_freq=d["constants"]["config_clock_frequency"], cpu_isa=d["constants"]["cpu_isa"]) +""".format(cpu=cpu, irq=cpu, sys_clk_freq=d["constants"]["config_clock_frequency"], cpu_isa=d["constants"]["cpu_isa"], cache_desc=cache_desc, tlb_desc=tlb_desc) dts += """ - }; -""" + {cpu_map} + }}; +""".format(cpu_map=cpu_map) # mor1kx elif cpu_name == "mor1kx":