view src/gearsTools/generate_context.pl @ 111:239bd73abac6

add gen context.h at generate_context.pl
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Thu, 28 Nov 2019 12:17:05 +0900
parents 435bfab09924
children f9df567f7f2d
line wrap: on
line source

#!/usr/bin/perl

use Getopt::Std;
use strict;

# 
# generrate Gears OS context heaader and initializer from CbC sources
#
# CodeGear
# 
# get stub information from # *.c
#     __code taskManager_stub(struct Context* cbc_context) {
# 
# generate CodeGear indexn in context.h
#     C_taskManager,
# 
# generate CodeGear stub reference in context.h
#     extern __code taskManager_stub(struct Context*);
# 
# generate CodeGear stub reference in $name-context.h for each module
#     cbc_context->code[C_taskManager]   = taskManager_stub;
# 
# DataGear
# 
# get DataGear information from context.h
#     struct Worker {
#         int id;
#         struct Context* contexts;
#         enum Code execute;
#         enum Code taskSend;
#         enum Code taskRecive;
#         enum Code shutdown;
#         struct Queue* tasks;
#     } Worker;
# 
# generate typedefs and DataGear index in context.h
#     typedef struct Worker Worker;
#     D_Worker,
# 
# generate DataGear allocator in context.h
#      ALLOC_DATA(context, Worker);
#

my $ddir = "c";

our($opt_o,$opt_d,$opt_h,$opt_w);
getopts('o:d:hw');

my $name = $opt_o?$opt_o:"gears";

if ($opt_d) {
    $ddir = $opt_d;
}

if ( ! -d $ddir) {
    mkdir $ddir;
}

if ($opt_h) {
    print "$0  [-d distdir] [-h]\n";
    exit;
}

my %codeGear;
my %dataGear;
my %constructor;

{
  use FindBin;
  use lib "$FindBin::Bin/lib";

  use File::Spec;
  use Cwd 'getcwd';

  use Gears::Context;
  use Getopt::Std;

  my $output     = $opt_w ? "context.h" : "stdout";

  my @cbc_files;
  map { push(@cbc_files,File::Spec->rel2abs($_)); }  @ARGV;
  my $gears      = Gears::Context->new(compile_sources => \@cbc_files, find_root => "$FindBin::Bin/../", output => $output);
  my $data_gears = $gears->extraction_dg_compile_sources();
  my $g          = $gears->set_data_gear_header_path();

  #use DDP {deparse =>1};
  my $dg2path    = $gears->update_dg_each_header_path($data_gears,$g);
  my $tree = $gears->createImplTree_from_header($dg2path);
  $gears->tree2create_context_h($tree);
}

# gather module Information for code table initialization
for (@ARGV) {
    next if (/context.c/);
    &getStubInfo($_);
}

my (%mCodeGear) = (%codeGear);

# anyway we gather all Gears Information
while (<*.c test/*.c>) {
    next if (/context.c/);
    &getStubInfo($_);
}

&generateContext();

sub getStubInfo {
    my ($filename) = @_;
    open my $fd,"<",$filename or die("can't open $filename $!");
    while (<$fd>) {
        if (/^__code (\w+)_stub\(struct  *Context *\* *cbc_context\)/) {
            $codeGear{$1} = $filename;
        } elsif (/^(\w+)(\*)+  *create(\w+)\(([^]]*)\)/) {
            my $interface = $1;
            my $implementation = $3;
            my $constructorArgs = $4;
            $constructor{$implementation} = [$interface, $constructorArgs];
        }
    }

    open my $cx,"<","context.h" or die("can't open context.h $!");
    my $inUnionData = 0;
    while (<$cx>) {
        if (! $inUnionData) {
            if ( /^union Data/) {
                $inUnionData = 1;
            }
            next;
        }
        last if (/union Data end/);
        if (/struct (\w+) \{/) {
            $dataGear{$1} = 'struct';
        } elsif (/^\s{4}(\w+) (\w+);/) { # primitive type
            $dataGear{$1} = 'primitive';
        }
        $dataGear{"Context"} = "struct";
    }
}

sub generateContext {
    $codeGear{"start_code"} = "$ddir/$name-context.c";
    $codeGear{"exit_code"} = "$ddir/$name-context.c";
    $mCodeGear{"start_code"} = "$ddir/$name-context.c";
    $mCodeGear{"exit_code"} = "$ddir/$name-context.c";
    open my $fd,">","$ddir/extern.h" or die("can't open $ddir/extern.h $!");
    for my $code ( sort keys %codeGear ) {
        print $fd "extern __code ${code}_stub(struct Context*);\n";
    }
    for my $impl ( sort keys %constructor ) {
        my ($interface, $constructorArgs) = @{$constructor{$impl}};
        print $fd "extern ${interface}* create${impl}($constructorArgs);\n";
    }
    print $fd "\n";

    open my $fd,">","$ddir/enumCode.h" or die("can't open $ddir/enumCode.h $!");
    print $fd "enum Code {\n";
    for my $code ( sort keys %codeGear ) {
        print $fd "    C_${code},\n";
    }
    print $fd "};\n";
   
    my $code_init = ''; 
    for my $code ( sort keys %mCodeGear ) {
        $code_init .=  "    cbc_context->code[C_${code}]    = ${code}_stub;\n";
    }

    my $data_num = keys(%dataGear);
    $data_num++;
my $context_c = << "EOFEOF";
#ifndef CBCXV6
#include <stdlib.h>
#endif

#include "../context.h"

void initContext(struct Context* cbc_context) {
    cbc_context->heapLimit = sizeof(union Data)*ALLOCATE_SIZE;
    cbc_context->code = (__code(**) (struct Context*)) NEWN(ALLOCATE_SIZE, void*);
    cbc_context->data = NEWN(ALLOCATE_SIZE, union Data*);
    cbc_context->heapStart = NEWN(cbc_context->heapLimit, char);
    cbc_context->heap = cbc_context->heapStart;
    // cbc_context->codeNum = Exit;

$code_init

#include "dataGearInit.c"
    cbc_context->dataNum = $data_num;
}
EOFEOF

    open my $fd,">","$ddir/$name-context.c" or die("can't open $ddir/$name-context.c $!");
    print $fd $context_c;

my $meta_call = <<"EOFEOF";
__code meta(struct Context* cbc_context, enum Code next) {
    // printf("meta %d\\n",next);
    goto (cbc_context->code[next])(cbc_context);
}

__code parGotoMeta(struct Context* cbc_context, enum Code next) {
    cbc_context->task     = NULL;
    cbc_context->taskList = NULL;
    goto (cbc_context->code[Gearef(cbc_context, TaskManager)->taskManager->TaskManager.spawnTasks])(cbc_context);
}

__code start_code(struct Context* cbc_context) {
    goto meta(cbc_context, cbc_context->next);
}

__code start_code_stub(struct Context* cbc_context) {
    goto start_code(cbc_context);
}

__code exit_code(struct Context* cbc_context) {
    // free(cbc_context->code);
    // free(cbc_context->data);
    // free(cbc_context->heapStart);
    goto exit_code(cbc_context);
}

__code exit_code_stub(struct Context* cbc_context) {
    goto exit_code(cbc_context);
}    

// end context_c
EOFEOF

print $fd $meta_call;

open my $fd,">","$ddir/enumData.h" or die("can't open $ddir/enumData.h $!");
print $fd "enum DataType {\n";
print $fd "    D_Code,\n";
for my $data ( sort keys %dataGear ) {
    print $fd "    D_${data},\n";
}
print $fd "};\n\n";

open my $fd,">","$ddir/typedefData.h" or die("can't open $ddir/typedefData.h $!");
for my $data ( sort keys %dataGear ) {
    if ($dataGear{$data} eq 'struct') {
        print $fd "typedef struct ${data} ${data};\n";
    }
}

open my $fd,">","$ddir/dataGearInit.c" or die("can't open $ddir/dataGearInit.c $!");
for my $data ( sort keys %dataGear ) {
    print $fd "    ALLOC_DATA(cbc_context, ${data});\n";
}
}

# end