@Override
		protected GridLocationMap<FGVertex, FGEdge> performInitialGridLayout(
				VisualGraph<FGVertex, FGEdge> g) throws CancelledException {

			GridLocationMap<FGVertex, FGEdge> gridLocations = new GridLocationMap<>();

			Map<FGVertex, Node> nodesByVertices = new HashMap<>();
			Collection<FGVertex> vertices = g.getVertices();
			List<Node> rows = new ArrayList<>();
			for (FGVertex v : vertices) {
				Node node = new Node(v);
				nodesByVertices.put(v, node);
				rows.add(node);
			}
			Collections.sort(rows,
				(n1, n2) -> n1.v.getVertexAddress().compareTo(n2.v.getVertexAddress()));

			for (int i = 0; i < rows.size(); i++) {
				Node node = rows.get(i);
				node.row = i;
				gridLocations.row(node.v, i);
			}

			FunctionGraph fg = (FunctionGraph) g;
			Address entry = function.getEntryPoint();
			FGVertex source = fg.getVertexForAddress(entry);
			treeify(g, source, nodesByVertices);

			Node node = nodesByVertices.get(source);
			node.col = 1; // start column
			gridLocations.col(source, node.col);
			assignColumns(source, nodesByVertices, gridLocations);

			//Msg.out("grid: " + gridLocations.toStringGrid());

			return gridLocations;
		}
A simple layout that is used during testing
Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/graph/layout/TestFGLayoutProvider.java