From aac34f011f37a7590b14c9e3f4169d9e73be670c Mon Sep 17 00:00:00 2001
From: Sebastien Bourdeauducq <sb@m-labs.hk>
Date: Sun, 30 Nov 2014 22:29:26 +0800
Subject: [PATCH] gensoc: support user-defined CSR regions

---
 make.py                     |  4 +--
 misoclib/gensoc/__init__.py |  9 ++++++-
 misoclib/gensoc/cpuif.py    | 51 +++++++++++++++++--------------------
 3 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/make.py b/make.py
index 99a12bb6f..efec55ea3 100755
--- a/make.py
+++ b/make.py
@@ -152,7 +152,7 @@ CPU type:  {}
 			flash_boot_address = None
 		mem_header = cpuif.get_mem_header(soc.cpu_memory_regions, flash_boot_address)
 		write_to_file("software/include/generated/mem.h", boilerplate + mem_header)
-		csr_header = cpuif.get_csr_header(soc.csr_base, soc.csrbankarray, soc.interrupt_map)
+		csr_header = cpuif.get_csr_header(soc.cpu_csr_regions, soc.interrupt_map)
 		write_to_file("software/include/generated/csr.h", boilerplate + csr_header)
 		for sdram_phy in ["sdrphy", "ddrphy"]:
 			if hasattr(soc, sdram_phy):
@@ -160,7 +160,7 @@ CPU type:  {}
 				write_to_file("software/include/generated/sdram_phy.h", boilerplate + sdram_phy_header)
 
 	if actions["build-csr-csv"]:
-		csr_csv = cpuif.get_csr_csv(soc.csr_base, soc.csrbankarray)
+		csr_csv = cpuif.get_csr_csv(soc.cpu_csr_regions)
 		write_to_file(args.csr_csv, csr_csv)
 
 	if actions["build-bios"]:
diff --git a/misoclib/gensoc/__init__.py b/misoclib/gensoc/__init__.py
index 2e5e75869..2e5f491ec 100644
--- a/misoclib/gensoc/__init__.py
+++ b/misoclib/gensoc/__init__.py
@@ -14,7 +14,6 @@ from misoclib.sdram import dfii
 from misoclib.sdram.minicon import Minicon
 
 class GenSoC(Module):
-	csr_base = 0xe0000000
 	csr_map = {
 		"crg":					0, # user
 		"uart":					1, # provided by default
@@ -41,6 +40,7 @@ class GenSoC(Module):
 		self.l2_size = l2_size
 		self.cpu_type = cpu_type
 		self.cpu_memory_regions = []
+		self.cpu_csr_regions = [] # list of (name, origin, busword, csr_list/Memory)
 		self._rom_registered = False
 
 		# Wishbone
@@ -103,6 +103,9 @@ class GenSoC(Module):
 	def add_cpu_memory_region(self, name, origin, length):
 		self.cpu_memory_regions.append((name, origin, length))
 
+	def add_cpu_csr_region(self, name, origin, busword, obj):
+		self.cpu_csr_regions.append((name, origin, busword, obj))
+
 	def do_finalize(self):
 		if not self._rom_registered:
 			raise FinalizeError("Need to call GenSoC.register_rom()")
@@ -115,6 +118,10 @@ class GenSoC(Module):
 		self.submodules.csrbankarray = csrgen.BankArray(self,
 			lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
 		self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses())
+		for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
+			self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), csrs)
+		for name, memory, mapaddr, mmap in self.csrbankarray.srams:
+			self.add_cpu_csr_region(name, 0xe0000000+0x800*mapaddr, flen(rmap.bus.dat_w), memory)
 
 		# Interrupts
 		for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)):
diff --git a/misoclib/gensoc/cpuif.py b/misoclib/gensoc/cpuif.py
index 994f9ddb3..57d365b8e 100644
--- a/misoclib/gensoc/cpuif.py
+++ b/misoclib/gensoc/cpuif.py
@@ -68,37 +68,34 @@ def _get_rw_functions(reg_name, reg_base, nwords, busword, read_only):
 		r += "}\n"
 	return r
 
-def get_csr_header(csr_base, bank_array, interrupt_map):
+def get_csr_header(regions, interrupt_map):
 	r = "#ifndef __GENERATED_CSR_H\n#define __GENERATED_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"
-		busword = flen(rmap.bus.dat_w)
-		for csr in csrs:
-			nr = (csr.size + busword - 1)//busword
-			r += _get_rw_functions(name + "_" + csr.name, reg_base, nr, busword, isinstance(csr, CSRStatus))
-			reg_base += 4*nr
-		try:
-			interrupt_nr = interrupt_map[name]
-		except KeyError:
-			pass
+	for name, origin, busword, obj in regions:
+		if isinstance(obj, Memory):
+			fullname = name + "_" + memory.name_override
+			r += "#define "+fullname.upper()+"_BASE "+hex(origin)+"\n"
 		else:
-			r += "#define "+name.upper()+"_INTERRUPT "+str(interrupt_nr)+"\n"
-	for name, memory, mapaddr, mmap in bank_array.srams:
-		mem_base = csr_base + 0x800*mapaddr
-		fullname = name + "_" + memory.name_override
-		r += "#define "+fullname.upper()+"_BASE "+hex(mem_base)+"\n"
+			r += "\n/* "+name+" */\n"
+			r += "#define "+name.upper()+"_BASE "+hex(origin)+"\n"
+			for csr in obj:
+				nr = (csr.size + busword - 1)//busword
+				r += _get_rw_functions(name + "_" + csr.name, origin, nr, busword, isinstance(csr, CSRStatus))
+				origin += 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):
+def get_csr_csv(regions):
 	r = ""
-	for name, csrs, mapaddr, rmap in bank_array.banks:
-		reg_base = csr_base + 0x800*mapaddr
-		busword = flen(rmap.bus.dat_w)
-		for csr in csrs:
-			nr = (csr.size + busword - 1)//busword
-			r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, reg_base, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
-			reg_base += 4*nr
+	for name, origin, busword, obj in regions:
+		if not isinstance(obj, Memory):
+			for csr in obj:
+				nr = (csr.size + busword - 1)//busword
+				r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
+				origin += 4*nr
 	return r