+#print STDERR;
+
+our $name;
+our $total_count;
+our $total_real_count;
+our $max_nrows=0;
+our $max_rowsz=0;
+
+sub wrtoplevel () {
+ my $cs = $count{$name};
+ my $total = 0; $total += $_ foreach values %$cs;
+ return unless $total;
+ print "module ${which}_$name(){ ////toplevel\n";
+ my $rowsz = ceil(sqrt($total));
+ my $nrows = ceil($total / $rowsz);
+ $total_count += $total;
+ $total_real_count += $total if $name =~ m/^[A-Z][a-z]+$/;
+ $max_nrows = $nrows if $nrows > $max_nrows;
+ $max_rowsz = $rowsz if $rowsz > $max_rowsz;
+ my $ix = 0;
+ printf "// %s %-10s total=%2d rowsz=$rowsz nrows=$nrows\n",
+ $which, "$name", $total;
+ foreach my $nspots (sort keys %$cs) {
+ my $c = $cs->{$nspots};
+ print <<END;
+ union(){
+ Frame(\$phase, token_pitch * [ $rowsz + 1.00, $nrows + 0.50 ]);
+ \$nspots = $nspots;
+END
+ while ($c--) {
+ my $xy = sprintf "[ %5.1f, %5.1f ]",
+ int($ix / $nrows) - 0.5 * ($rowsz-1),
+ $ix % $nrows - 0.5 * ($nrows-1);
+ print " translate(token_pitch * $xy) Token_L();\n";
+ $ix++;
+ }
+ print <<END;
+ };
+END
+ }
+ print "}\n";
+}
+
+foreach $name (sort keys %count) {
+ wrtoplevel();
+}
+
+print <<END;
+// $which total_count=$total_count total_real_count=$total_real_count
+// $which max_rowsz=$max_rowsz max_nrows=$max_nrows
+END
+
+STDOUT->error and die $!;