#!/usr/pkg/bin/perl
#  layer
#   0   1st laer  Silicon   coarse Mark 1
#   1   1st layer Silicon               1

#   2   2nd layer label and resist      2
#   3   not used
#   4   not used
#   10  Fine (Field) Mark label         -
#   20  die frame                     
#   30  corner label                    2
#   31  global label A ..I              2
#   32  global labe  1 .. 12            2

use warnings;
use strict;
use GDS2;
use Getopt::Std;

my $VERSION = "2026-04-27 23:01";

push(@INC, "../Perl_GDSII_Tutorial/code");
push(@INC, "../vernier-J10/");
push(@INC, ".");
require 'arc3.pm';
require 'text2gds.pm';
require 'vernier5.pm';
require 'LocalGlobalMarks.pm';


# ----------------------------------------------------------
#                    Dicing Mark  L
# ----------------------------------------------------------
sub WaferBoundary   {
    my ($args)     = @_;
    my ($layer)    =  $args -> { -layer };
    my ($size)     =  $args -> { -size };
    my ($gds2File) =  $args -> { -gds2File };

    my $name    = sprintf("Wafer-L%03d-S%0d",  $layer, $size/1000);
    $gds2File -> printBgnstr  (-name => $name);

    my @COORD = arc3::arc({
	    -x => 0, -y => 0, -radius => $size, -polygon_count => 72,
		-start_angle =>      - 71.03 - 3,
		-end_angle =>    180 + 71.03 - 3,
		-direction => 0,
			  });
    $gds2File -> printBoundary  (
	-xy => [ @COORD	],
	-layer => $layer,
	);
    $gds2File -> printEndstr();
    return $name;
}
sub ScribeL  { 
    my ($args)     = @_;
    my ($LX)        = $args -> { -lengthX }; # micro meter
    my ($LY)        = $args -> { -lengthY }; # micro meter
    my ($W)        = $args -> { -width }; # micro meter
    my ($G)        = $args -> { -gap }; # micro meter
    my ($layer)    =  $args -> { -layer};
    my ($gds2File) =  $args -> { -gds2File};

    my $name    = sprintf("scribe-X%03d-Y%03d",  $LX, $LY);
    $gds2File -> printBgnstr  (-name => $name);
    $gds2File -> printBoundary  (
        -xy=> [ 
              $G/2,        $G/2,
              $G/2 + $LX,   $G/2,
              $G/2 + $LX,   $G/2 + $W,
              $G/2 + $W,   $G/2 + $W,
              $G/2 + $W,   $G/2 + $LY,
              $G/2,        $G/2 + $LY,
        ],
        -layer=> $layer);
    $gds2File -> printBoundary  (
        -xy=> [  $LX + $G/2,    -$G/2, 2 * $LX + $G/2, -$G/2, 
		                       2 * $LX + $G/2, -$G/2 - $W, 
                 $LX + $G/2,     -$G/2 - $W
	],
        -layer=> $layer);
    $gds2File -> printBoundary  (
        -xy=> [  -$G/2,       $LY + $G/2,  -$G/2,      2 * $LY + $G/2, 
                                      -$G/2 - $W, 2 * $LY + $G/2, 
                 -$G/2 - $W,  $LY + $G/2], 
        -layer=> $layer);

    $gds2File -> printEndstr();
    return $name;
}
# ----------------------------------------------------------
#                    Coarse Mark
# ----------------------------------------------------------
sub CoarseMark {
    my ($args)	= @_;
    my ($size)		= $args -> {-size}; # um
    my ($width)		= $args -> {-width}; # um
    my ($cross)		= $args -> {-cross}; # um
    my $gds2File	= $args -> {-gds2File};
    my $name 		= sprintf("CoarseMark-%3.1f", $size);
    my $S  = $size / 2;
    my $W  = $width;
    my $W2 = $width / 2;
    my $C  = $cross/ 2;
    $gds2File	-> printBgnstr( -name => $name);
    $gds2File   -> printBoundary (
	-xy => [
	     -$S, -$S,  -$S, $S, $S, $S, $S, -$S,
	     -$S + $W, -$S,
	     -$S + $W, -$S + $W,
	      $S - $W, -$S + $W,
	      $S - $W,  $S - $W,
	     -$S + $W,  $S - $W,
	     -$S + $W,  $S - $W,
	     -$S + $W, -$S
	]);
    $gds2File   -> printBoundary (
	-xy => [ -$C, -$W2, -$W2, -$W2,
		 -$W2, -$C,
		  $W2, -$C,
		  $W2, -$W2, $C, -$W2,  $C, $W2,
		  $W2,  $W2,
		  $W2,  $C,
		 -$W2,  $C,
		 -$W2,  $W2,
		 -$C,  $W2,
	]);
    $gds2File	-> printEndstr();
    return $name;
}
sub box10 {
    my ($args)		= @_;
    my $gds2File	= $args -> {-gds2File};
    my $name 		= sprintf("box10");

    $gds2File	-> printBgnstr( -name => $name);
    $gds2File	-> printBoundary( -xy =>
	[ -5,-5,  -5, 5,  5,5, 5, -5]
	);
    $gds2File	-> printEndstr();
    return $name;
}
# Fine and Alignment set for each corner
sub cornerMark {
    my ($args)		= @_;
    my ($Aname)		= $args -> {-Aname};
    my ($Fname)		= $args -> {-Fname};
    my $gds2File	= $args -> {-gds2File};

    my $name 		= sprintf("cornerMark");
    $gds2File	-> printBgnstr( -name => $name);
    # Coarse
#   $gds2File	-> printSref  ( -name => $Aname, -xy =>[0,0]) ;
    # Fine
    my $shift = 400;
    foreach my $i ( 0..4) {
	$gds2File	-> printSref  ( -name => $Fname, -xy => [- $shift, $i * 100 - $shift ]);
	$gds2File	-> printSref  ( -name => $Fname, -xy => [          $i * 100 - $shift, -$shift ]);
    }
        $gds2File	-> printSref  ( -name => $Fname, -xy => [ 0, 0 ]);
    $gds2File	-> printEndstr();
    return $name;
}

# ----------------------------------------------------------
#                    H E L P
# ----------------------------------------------------------
sub usage{
    my ($args)		= @_;
    my ($frame)		= $args -> {-frame}; # um

print STDERR <<HELP;
  synopsys:
     $0 [-h] [-S start] [ -s size] [ -l limit]
  where:
    -h      Show this help
    -f      frame size (default $frame um)
HELP
}
sub main {
## ----------------------------------------------------
##          M A I N  R O U T I N E 
## ----------------------------------------------------
our %opts;                                                        
our @ARGV;

my $filename = $0;                              # ---  set filename with the same as this script
   $filename =~ s/^[0-9]+\.//;
   $filename =~ s/\.txt$//;                     # ---  Strip '.txt' part
                                                #     
my $VERSION2 = $VERSION;
    $VERSION2 =~ s/ /-/g;
    $VERSION2 =~ s/:/./g;

my $C =  9500;		# inner mark location (backup mark inside)
my $F = 10000;		# frame size

##my $X = $F - 200;	# outer mark location

my $frame = $F;

# ------------------------------------------------
#       process argment on command line
# ------------------------------------------------
getopts('f:h', \%opts);

if ($opts{'h'}) { usage({}); exit;}
if ($opts{'f:'}) {  $frame  = $opts{'f'}   };


my $gds_name = sprintf("%s-Frame-%2.1f-%s.gds", $filename, $F/500, $VERSION2);
my $gds2File = new GDS2(-fileName=> '>'. $gds_name);

$gds2File -> printInitLib(-name=>'LibraryName',
                          -uUnit =>  0.00025,
                          -dbUnit => 0.00025/1000000);
## ----------------------------------------------------
##                 call two sub routine
## ----------------------------------------------------
my $scribe  = ScribeL   ({ -width => 20, -layer => 0,
                               -lengthX => 100,
                               -lengthY => 200,                        
                               -gap => 120,
                               -gds2File => $gds2File});

my $cornerMark = Marks::Combo({
			-gds2File => $gds2File
		    });
my $CoarseMark = Marks::GlobalMark({-width =>  10, -length => 500, -gds2File => $gds2File});
my $LocalMark  = Marks::LocalMark({-W => 0.5, -L => 10, -G => 1.5, -N => 2, -gds2File => $gds2File});
## ----------------------------------------------------
##                   master structure
## ----------------------------------------------------
my $oneUnitName =  sprintf("OneUnit%02d", $F * 2/1000) ;

my $WaferBoundary =
WaferBoundary({ -gds2File => $gds2File, -layer => 10, -size => 50000});

$gds2File -> printBgnstr( -name => $oneUnitName);
foreach my $P ( $C ) { ## , $X) {
    $gds2File -> printSref( -name => $cornerMark, -xy => [ $P, $P]                );
    $gds2File -> printSref( -name => $cornerMark, -xy => [-$P, $P], -angle => 90  );
    $gds2File -> printSref( -name => $cornerMark, -xy => [-$P,-$P], -angle => 180 );
    $gds2File -> printSref( -name => $cornerMark, -xy => [ $P,-$P], -angle => 270 );

    $gds2File -> printSref( -name => $CoarseMark, -xy => [ $P, $P]                );
    $gds2File -> printSref( -name => $CoarseMark, -xy => [-$P,-$P]);

#   $gds2File -> printSref( -name => $CoarseMark, -xy => [-$P,  0]);
    $gds2File -> printSref( -name => $CoarseMark, -xy => [ $P,  0]);

#   $gds2File -> printSref( -name => $CoarseMark, -xy => [ 0,  -$P]);
    $gds2File -> printSref( -name => $CoarseMark, -xy => [ 0,   $P]);
}

#$gds2File -> printSref( -name => $bigFrame,   -xy => [0,0]);
#$gds2File -> printSref( -name => $smallFrame, -xy => [0,0]);

# -----------------------------------------------------
#                    place scribe mark
# -----------------------------------------------------
    $gds2File -> printSref( -name => $scribe, -xy => [ -$frame, -$frame]);
    $gds2File -> printSref( -name => $scribe, -xy => [  $frame, -$frame], -angle=>  180, -reflect=>  1);
    $gds2File -> printSref( -name => $scribe, -xy => [  $frame,  $frame], -angle=>  180);
    $gds2File -> printSref( -name => $scribe, -xy => [ -$frame,  $frame], -reflect => 1);

#$gds2File -> printSref( -name => $Vertical,   -xy => [0,0]);

# -----------------------------------------------------
#                    place external boundary
# -----------------------------------------------------
$gds2File -> printBoundary
    (-xy => [ $F, $F, -$F, $F, -$F, -$F, $F, -$F], -layer => 20);


my $S = 10000;    # span/2
my $s = 10000/3;  # span / $count
$gds2File -> printAref(-name => 'vernierx3',
		       -columns => 3,
		       -rows => 3,
		       -xy   => [ -$S + $s, -$S + $s,
				   $S + $s, -$S + $s,
				  -$S + $s,  $S + $s,
		       ]);
my $charIndex = 0;
foreach my $y ( -1, 0,  1) {
    foreach my $x ( -1, 0,  1) {
	text2gds::text_flat( $x * 6666.666 + 0.9 , $y * 6666.666, 31, 0.05, chr($charIndex++  + 0x41),
			     $gds2File);
    }
}
$gds2File -> printEndstr();

my @PLACEMENT = (
    [  qw(   0 1 1 0  )  ],
    [  qw(   1 1 1 1  )  ],
    [  qw(   1 1 1 1  )  ],
    [  qw(   0 1 1 0  )  ],
    );
#print STDERR join(':', qw( 0 1 0 1))."\n";

my $bigFrame =
vernier::Frame_4x3({ -gds2File => $gds2File,
			 -frame_sizeX => 400, 
			 -frame_sizeY => 300, -width => 20});
my $smallFrame =
vernier::Frame_4x3({ -gds2File => $gds2File,
			 -frame_sizeX => 40, 
			 -frame_sizeY => 30, -width => 2});

vernier::vernierx3({ -gds2File       => $gds2File,
			 -smallFrame => $smallFrame,
			 -bigFrame   => $bigFrame
		   });

my($offsetX,$offsetY) = (-30000, -30000);

$gds2File -> printBgnstr( -name => 'Wafer');
my $dieIndex = 1;
foreach my $y ( 0 .. $#PLACEMENT) {
#    print STDERR __LINE__. ' ' . $y. " ";
    my @ROW = $PLACEMENT[$y]-> [0];   # not used for now


    foreach my $x ( 0 .. 3) {
	my $bit =  $PLACEMENT[$y] -> [$x];
	my $XXX = $x * 20000 - 30000;
	my $YYY = $y * 20000 - 30000;
	if ($bit == 1 ) {
	$gds2File -> printSref( -name => $oneUnitName,
				-xy   => [$x * 20000 + $offsetX, $y * 20000 + $offsetY]);
	my $stringA = sprintf(" %d %d %s", $x - 2, $y - 2 , 'A');
	text2gds::text_flat( -9800 + $XXX,
			     -9800 + $YYY,
			     30, 5, $stringA, $gds2File);
	
	my $stringB = sprintf(" %d %d %s", $x - 2, $y - 2 , 'B');
	text2gds::text_flat(  9800 + $XXX,
			     -9800 + $YYY,
			     30, 5, $stringB, $gds2File);

	my $stringC = sprintf(" %d %d %s", $x - 2, $y - 2 , 'C');
	text2gds::text_flat(  9800 + $XXX,
			      9800 + $YYY,
			     30, 5, $stringC, $gds2File);

	my $stringD = sprintf(" %d %d %s", $x - 2, $y - 2 , 'D');
	text2gds::text_flat( -9800 + $XXX,
			      9800 + $YYY,
			     30, 5, $stringD, $gds2File);
	foreach my $xx ( -1, 0, 1 ){
	    foreach my $yy ( -1, 0, 1 ){
		text2gds::text_flat( $XXX + $xx * 6666.67 - 0.9,
				     $YYY + $yy * 6666.67,
				     32, 0.05 , $dieIndex, $gds2File);
	    }
	}
	$dieIndex++
	}
    }
}
$gds2File -> printSref ( -name => $WaferBoundary, -xy => [0,0]);
$gds2File -> printEndstr();

$gds2File -> printEndlib();

print $gds_name,"\n";   # trick to use  klayout `perl AlignmentMark2`
};

# -----------------------------------------------------
#                    call sub main( )
# -----------------------------------------------------

main ();
__END__
;; ----- eval-region stuff
(require 'time-stamp)
(add-hook 'write-file-hooks 'time-stamp)
(setq time-stamp-active t)
;; (setq time-stamp-time-zone "UTC")
(setq time-stamp-time-zone nil)
(setq time-stamp-format "%Y-%02m-%02d %02H:%02M");
(setq time-stamp-start "$VERSION = \"") ;
(setq time-stamp-end "\"") ;
(setq time-stamp-line-limit 20) ; ; default is 8
