This patch creates static.dot visualizing the coreboot device tree (v2)

create pngs with
 $ fdp -o static.png -Tpng static.dot
or
 $ dot -o static.png -Tpng static.dot

edge colors:
 blue: parent->self relation
 red: self->child relation
 green: self->sibling relation
 pink: self->next relation

TODO/ideas:
 node colors according to device type?
 put devices belonging to the same parent on the same level
 add an agenda

I don't think this should be committed yet, it's just a rough try I created
to debug a problem with the device tree code / resource allocator.

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>


Index: util/newconfig/config.g
===================================================================
--- util/newconfig/config.g	(revision 534)
+++ util/newconfig/config.g	(working copy)
@@ -93,6 +93,7 @@
 	dict = 4
 	statement = 5
 	dump = 6
+	gengraph = 7
 
 	def __init__(self, *level):
 		self.__level = level
@@ -682,6 +683,15 @@
 		else:
 			name = "%s %s" % (name, self.path)
 		return name
+
+	def graph_name(self):
+		name = ""
+		name = "%s_%d" % (self.type_name, self.instance)
+#		if (self.chip_or_device == 'chip'):
+		name = "%s %s %s" % (name, self.part, self.parent.type_name)
+#		else:
+#			name = "%s %s" % (name, self.path)
+		return name
 			
 	def dumpme(self, lvl):
 		"""Dump information about this part for debugging"""
@@ -976,6 +986,56 @@
 		setdict(self.uses_options, name, o)
 		exportoption(o, self.image.exported_options)
 
+	def gengraph(self, file, pass_num):
+		"""Generate static device tree graph for this part. Two passes
+		are used - the first generates type information, and the second
+		generates instance information"""
+		if (pass_num == 0):
+			if (self.chip_or_device == 'chip'):
+				return;
+			else:
+				if (self.instance):
+					file.write("%s[shape=box, label=\"%s\"];\n" \
+						% (self.instance_name, self.graph_name()))
+				else:
+					file.write("node [shape=circle] dev_root;\n")
+			return
+		# This is pass the second, which is pass number 1
+		# this is really just a case statement ...
+
+		if (self.chip_or_device == 'chip'):
+			if (self.instance == 0):
+				self.instance_name = "dev_root"
+				file.write("%s -> %s ;\n" % (self.instance_name, self.firstchilddevice().instance_name))
+			return
+
+		# Don't print duplicate devices, just print their children
+		if (self.dup):
+			return
+
+		file.write("%s -> %s [color=\"#0000ff\"]\n" % \
+				(self.firstparentdevice().instance_name, self.instance_name))
+		links = 0
+		bus = self
+		while(bus and (bus.path == self.path)):
+			child = bus.firstchilddevice()
+			if (child or (bus != self) or (bus.next_sibling and (bus.next_sibling.path == self.path))):
+				if (child):
+					file.write("%s -> %s [color=\"#ff0000\"]\n" % (self.instance_name, child.instance_name))
+				links = links + 1
+			if (1):	
+				bus = bus.next_sibling
+			else:
+				bus = 0
+		sibling = self.firstsiblingdevice(); 
+		if (sibling):
+			file.write("%s -> %s [color=\"#00ff00\"]\n" % (self.instance_name, sibling.instance_name))
+		chip = self.firstparentchip()
+		if (self.next_device):	
+			file.write("%s -> %s [color=\"#ff00ff\"]\n" % (self.instance_name, self.next_device.instance_name))
+		return
+
+
 # -----------------------------------------------------------------------------
 #                    statements 
 # -----------------------------------------------------------------------------
@@ -2254,7 +2314,9 @@
 	file.write("#include <device/pci.h>\n")
 	for path in image.getconfigincludes().values():
 		file.write("#include \"%s\"\n" % path)
+	file.write("\n/* pass 0 */\n")
 	gencode(image.getroot(), file, 0)
+	file.write("\n/* pass 1 */\n")
 	gencode(image.getroot(), file, 1)
 	file.close()
 
@@ -2278,6 +2340,36 @@
 		kid = kid.next_sibling
 	debug.info(debug.gencode, "DONE GENCODE")
 
+def writegraph(image):
+	filename = os.path.join(img_dir, "static.dot")
+	print "Creating", filename
+	file = safe_open(filename, 'w+')
+	file.write("digraph devicetree {\n")
+	gengraph(image.getroot(), file, 0)
+	gengraph(image.getroot(), file, 1)
+	file.write("}\n")
+	file.close()
+
+def gengraph(part, file, pass_num):
+	debug.info(debug.gengraph, "GENGRAPH ME is")
+	part.gengraph(file, pass_num)
+	# dump the siblings -- actually are there any? not sure
+	debug.info(debug.gengraph, "GENGRAPH SIBLINGS are")
+	kid = part.next_sibling
+	while (kid):
+		kid.gengraph(file, pass_num)
+		kid = kid.next_sibling
+	# now dump the children 
+	debug.info(debug.gengraph, "GENGRAPH KIDS are")
+	if (part.children):
+		gengraph(part.children, file, pass_num)
+	kid = part.next_sibling
+	while (kid):
+		if (kid.children):
+			gengraph(kid.children, file, pass_num)
+		kid = kid.next_sibling
+	debug.info(debug.gengraph, "DONE GENGRAPH")
+
 def verifyparse():
 	"""Add any run-time checks to verify that parsing the configuration
 	was successful"""
@@ -2343,6 +2435,7 @@
 		writeinitincludes(image)
 		writeimagemakefile(image)
 		writeldoptions(image)
+		writegraph(image)
 
 	writemakefilesettings(target_dir)
 	writemakefile(target_dir)
