changeset 110:8c7c1ea49f21

impl auto gen context tools
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Wed, 27 Nov 2019 21:21:42 +0900
parents 4f9d95dc4efd
children 239bd73abac6
files src/gearsTools/lib/Gears/Context.pm src/gearsTools/lib/Gears/Context/Template/XV6.pm src/gearsTools/lib/Gears/Util.pm src/plautogen/impl/SingleLinkedStack.h src/plautogen/interface/Meta.h src/plautogen/interface/Stack.h src/plautogen/interface/UInteger.h
diffstat 7 files changed, 490 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gearsTools/lib/Gears/Context.pm	Wed Nov 27 21:21:42 2019 +0900
@@ -0,0 +1,200 @@
+package Gears::Context;
+
+use strict;
+use warnings;
+
+use Gears::Util;
+use Gears::Context::Template::XV6;
+use Carp qw/croak/;
+
+sub new {
+  my ($class, %args) = @_;
+  my $self = {
+    data_gears_with_count => {},
+    find_root => $args{find_root} // ".",
+    output   => $args{output},
+  };
+
+  if ($args{compile_sources}) {
+    $self->{compile_sources} = $args{compile_sources};
+    map { Gears::Util->file_checking($_); } @{$self->{compile_sources}};
+  }
+
+  return bless $self, $class;
+}
+
+
+sub extraction_dg_compile_sources {
+  my $self = shift;
+  my %counter;
+  for my $cbc_file (@{$self->{compile_sources}}) {
+    open my $fh , '<', $cbc_file;
+    while (my $line = <$fh>) {
+       if ($line =~ /#interface\s*"(.*)\.h"/ || $line =~ /^\/\/\s*use\s*"(.*)\.h"/) {
+          $self->{data_gears_with_count}->{$1}->{caller}->{$cbc_file}++;
+          $counter{interfaces}->{$1}++;
+          next;
+       }
+
+       if ($line =~ /^(\w+)(\*)+  *create(\w+)\(([^]]*)\)/) {
+          my $interface = $1;
+          my $implementation = $3;
+          $self->{data_gears_with_count}->{$interface}->{caller}->{$cbc_file}++;
+          $self->{data_gears_with_count}->{$implementation}->{caller}->{$cbc_file}++;
+          $counter{interfaces}->{$interface}++;
+          $counter{impl}->{$implementation}++;
+          next;
+       }
+
+       if ($line =~ /Gearef\(context,\s*(\w+)\)/) {
+          my $implementation = $1;
+          $counter{impl}->{$implementation}++;
+          $self->{data_gears_with_count}->{$implementation}->{caller}->{$cbc_file}++;
+          next;
+       }
+
+       if ($line =~ /ALLOCATE_(?:PTR_)?ARRAY\(context,\s*(\w+),[\s\w]+\)/) {
+          my $implementation = $1;
+          $counter{impl}->{$implementation}++;
+          $self->{data_gears_with_count}->{$implementation}->{caller}->{$cbc_file}++;
+          next;
+       }
+
+       if ($line =~ /ALLOCATE_DATA_GEAR\((\w+),\s*(\w+)\)/) {
+          my $implementation = $2;
+          $counter{impl}->{$implementation}++;
+          $self->{data_gears_with_count}->{$implementation}->{caller}->{$cbc_file}++;
+          next;
+       }
+
+       #TaskManagerImpl* taskManager = (TaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+       if ($line =~ /\((\w+)\*\)GearImpl\(context,\s*(\w+),\s*(\w+)\)/) {
+          my $interface = $2;
+          my $implementation = $1;
+          $self->{data_gears_with_count}->{$interface}->{caller}->{$cbc_file}++;
+          $counter{interfaces}->{$interface}++;
+          $counter{impl}->{$implementation}++;
+          next;
+       }
+
+       if ($line =~ /^__code/) {
+         while ($line =~ /struct (\w+)\s*\*/g) {
+           next if $1 eq "Context";
+           $self->{data_gears_with_count}->{$1}->{caller}->{$cbc_file}++;
+           next if (exists $counter{interfaces}->{$1});
+           $counter{impl}->{$1}++;
+         }
+       }
+    }
+    close $fh;
+  }
+  $counter{interfaces}->{Meta}++;
+  $counter{interfaces}->{TaskManager}++;
+  $self->{data_gears_with_count}->{Meta}++;
+  $self->{data_gears_with_count}->{TaskManager}++;
+  return \%counter;
+}
+
+sub set_data_gear_header_path {
+  my $self = shift;
+  my @data_gears_name;
+  if (@_) {
+    @data_gears_name = @_;
+  } else {
+    map { push (@data_gears_name,$_) if $_ ne "Context" } keys %{$self->{data_gears_with_count}};
+  }
+  return _find_headers($self->{find_root},\@data_gears_name);
+}
+
+sub update_dg_each_header_path {
+  my ($self, $dgs, $dg2path) = @_;
+  my $new_dgs;
+  for my $kind (keys %$dgs) {
+    for my $dg_name (keys %{$dgs->{$kind}}) {
+      if ($dg2path->{$dg_name}) {
+        $new_dgs->{$kind}->{$dg_name} = $dg2path->{$dg_name};
+      } else {
+        croak "failed trans header $dg_name\n";
+      }
+    }
+  }
+  return $new_dgs;
+}
+
+sub tree2create_context_h {
+  my ($self, $dg2path) = @_;
+
+  my $data_struct_str = $dg2path ? $self->tree2data_struct_str($dg2path) : "\n";
+
+  my $output = $self->_select_output();
+  Gears::Context::Template::XV6->emit_top_header($output);
+  Gears::Context::Template::XV6->emit_data_gears($output,$data_struct_str);
+  Gears::Context::Template::XV6->emit_last_header($output);
+  close $output;
+}
+
+sub _select_output {
+  my $self = shift;
+  print "$self->{output}\n";
+  if ($self->{output} eq  'stdout') {
+    return *STDOUT;
+  }
+  open my $fh, '>', $self->{output};
+  return $fh;
+}
+
+sub tree2data_struct_str {
+  my ($self, $dg_str) = @_;
+  my $data_struct_str  = "";
+  for my $interface (sort keys %$dg_str) {
+    $data_struct_str .= Gears::Util->h2context_str($dg_str->{$interface}->{elem});
+    next unless ($dg_str->{$interface}->{impl});
+    for my $impl (sort keys %{$dg_str->{$interface}->{impl}}) {
+       $data_struct_str .= Gears::Util->h2context_str($dg_str->{$interface}->{impl}->{$impl});
+    }
+  }
+  return $data_struct_str;
+}
+
+sub createImplTree_from_header {
+  my ($self, $dg2path) = @_;
+  my %dg_str = ();
+
+  my $inters = $dg2path->{interfaces};
+  my $impls = $dg2path->{impl};
+
+  use Data::Dumper;
+  use DDP {deparse => 1};
+  print Dumper $dg2path;
+  p $self;
+
+  map { $dg_str{$_}->{elem} = Gears::Util->parse_interface($inters->{$_}) } keys %$inters;
+
+  map {
+    my $res = Gears::Util->parse($impls->{$_});
+    if ($res->{isa}) {
+        $dg_str{$res->{isa}}->{impl}->{$_} = $res;
+    } else {
+        $dg_str{$_}->{elem} = $res;
+    }
+  } keys %$impls;
+  return \%dg_str;
+}
+
+sub _find_headers {
+  my ($search_bash_path, $targets) = @_;
+  my %res;
+  map { $res{$_}++ } @$targets;
+
+  my $header_paths = Gears::Util->find_headers_path($search_bash_path);
+  map {
+    /(\w+)\.h/;
+    my $header_tile = $1;
+    if (exists $res{$header_tile}){
+      $res{$header_tile} = $_;
+    }
+  } @$header_paths;
+  return \%res;
+}
+
+1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gearsTools/lib/Gears/Context/Template/XV6.pm	Wed Nov 27 21:21:42 2019 +0900
@@ -0,0 +1,194 @@
+package Gears::Context::Template::XV6;
+use strict;
+use warnings;
+
+sub emit_top_header {
+  my ($class, $out) = @_;
+my $str =  << 'EOFEOF';
+/* Context definition for llrb example */
+// #ifdef CBC_CONTEXT_H  does not work well
+#define CBC_CONTEXT_H
+// #include <stdlib.h>
+// #include <pthread.h>
+#ifdef USE_CUDAWorker
+#include <cuda.h>
+#include <driver_types.h>
+#include <cuda_runtime.h>
+#include "helper_cuda.h"
+#endif
+
+#ifndef NULL
+# if defined __GNUG__ && \
+    (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
+#  define NULL (__null)
+# else
+#  if !defined(__cplusplus)
+#   define NULL ((void*)0)
+#  else
+#   define NULL (0)
+#  endif
+# endif
+#endif
+
+#ifdef XV6KERNEL
+extern void*           kmalloc (int order);
+#define calloc(a,b)  kmalloc((a)*(b))
+#define free(a)  kfree(a)
+#else
+#define calloc(a,b)  malloc((a)*(b))
+#define free(a)  free(a)
+#endif
+
+#define ALLOCATE_SIZE 20000000
+#define NEW(type) (type*)(calloc(1, sizeof(type)))
+#define NEWN(n, type) (type*)(calloc(n, sizeof(type)))
+
+#define ALLOC_DATA(cbc_context, dseg) ({\
+    Meta* meta = (Meta*)cbc_context->heap;\
+    meta->type = D_##dseg;\
+    meta->size = sizeof(dseg);\
+    meta->len = 1;\
+    cbc_context->heap += sizeof(Meta);\
+    cbc_context->data[D_##dseg] = cbc_context->heap; cbc_context->heap += sizeof(dseg); (dseg *)cbc_context->data[D_##dseg]; })
+
+#define ALLOC_DATA_TYPE(cbc_context, dseg, t) ({\
+    Meta* meta = (Meta*)cbc_context->heap;\
+    meta->type = D_##t;\
+    meta->size = sizeof(t);\
+    meta->len = 1;\
+    cbc_context->heap += sizeof(Meta);\
+    cbc_context->data[D_##dseg] = cbc_context->heap; cbc_context->heap += sizeof(t); (t *)cbc_context->data[D_##dseg]; })
+
+#define ALLOCATE(cbc_context, t) ({ \
+    Meta* meta = (Meta*)cbc_context->heap;\
+    cbc_context->heap += sizeof(Meta);\
+    union Data* data = cbc_context->heap; \
+    cbc_context->heap += sizeof(t); \
+    meta->type = D_##t; \
+    meta->size = sizeof(t);     \
+    meta->len = 1;\
+    data; })
+
+#define ALLOCATE_ARRAY(cbc_context, t, length) ({ \
+    Meta* meta = (Meta*)cbc_context->heap;\
+    cbc_context->heap += sizeof(Meta);\
+    union Data* data = cbc_context->heap; \
+    cbc_context->heap += sizeof(t)*length; \
+    meta->type = D_##t; \
+    meta->size = sizeof(t)*length; \
+    meta->len = length; \
+    data;   })
+
+#define ALLOCATE_PTR_ARRAY(cbc_context, dseg, length) ({\
+    Meta* meta = (Meta*)cbc_context->heap;\
+    cbc_context->heap += sizeof(Meta);\
+    union Data* data = cbc_context->heap; \
+    cbc_context->heap += sizeof(dseg *)*length; \
+    meta->type = D_##dseg; \
+    meta->size = sizeof(dseg *)*length; \
+    meta->len = length; \
+    data; })
+
+#define ALLOCATE_DATA_GEAR(cbc_context, t) ({ \
+        union Data* data = ALLOCATE(cbc_context, t); \
+        Meta* meta = GET_META(data); \
+        meta->wait = createSynchronizedQueue(cbc_context); \
+        data; })
+
+#define ALLOC(cbc_context, t) (&ALLOCATE(cbc_context, t)->t)
+
+#define GET_META(dseg) ((Meta*)(((void*)dseg) - sizeof(Meta)))
+#define GET_TYPE(dseg) (GET_META(dseg)->type)
+#define GET_SIZE(dseg) (GET_META(dseg)->size)
+#define GET_LEN(dseg) (GET_META(dseg)->len)
+#define GET_WAIT_LIST(dseg) (GET_META(dseg)->wait)
+
+#define Gearef(cbc_context, t) (&(cbc_context)->data[D_##t]->t)
+
+// (SingleLinkedStack *)cbc_context->data[D_Stack]->Stack.stack->Stack.stack
+
+#define GearImpl(cbc_context, intf, name) (Gearef(cbc_context, intf)->name->intf.name)
+
+#include "c/enumCode.h"
+
+enum Relational {
+    EQ,
+    GT,
+    LT,
+};
+
+#include "c/enumData.h"
+#define NDIRECT 12 //fs.h
+
+struct Context {
+    enum Code next;
+    struct Worker* worker;
+    struct TaskManager* taskManager;
+    int codeNum;
+    __code (**code) (struct Context*);
+    union Data **data;
+    void* heapStart;
+    void* heap;
+    long heapLimit;
+    int dataNum;
+
+    // task parameter
+    int idgCount; //number of waiting dataGear
+    int idg;
+    int maxIdg;
+    int odg;
+    int maxOdg;
+    int gpu; // GPU task
+    struct Context* task;
+    struct Element* taskList;
+#ifdef USE_CUDAWorker
+    int num_exec;
+    CUmodule module;
+    CUfunction function;
+#endif
+    /* multi dimension parameter */
+    int iterate;
+    struct Iterator* iterator;
+    enum Code before;
+};
+
+typedef int Int;
+#ifndef USE_CUDAWorker
+typedef unsigned long long CUdeviceptr;
+#endif
+EOFEOF
+    print $out $str;
+}
+
+sub emit_data_gears {
+  my ($class, $out, $dgs) = @_;
+
+print $out "union Data {\n";
+print $out $dgs;
+print $out  <<'EOF';
+    struct Context Context;
+}; // union Data end       this is necessary for context generator
+typedef union Data Data;
+EOF
+}
+
+
+sub emit_last_header {
+  my($class, $out) = @_;
+  print $out <<'EOF';
+#include "c/typedefData.h"
+
+#include "c/extern.h"
+
+extern __code start_code(struct Context* cbc_context);
+extern __code exit_code(struct Context* cbc_context);
+extern __code meta(struct Context* cbc_context, enum Code next);
+//extern __code par_meta(struct Context* cbc_context, enum Code spawns, enum Code next);
+extern __code parGotoMeta(struct Context* cbc_context, enum Code next);
+extern void initContext(struct Context* cbc_context);
+
+// #endif
+EOF
+}
+
+1;
--- a/src/gearsTools/lib/Gears/Util.pm	Thu Nov 21 21:10:25 2019 +0900
+++ b/src/gearsTools/lib/Gears/Util.pm	Wed Nov 27 21:21:42 2019 +0900
@@ -41,7 +41,7 @@
   my ($file,$code_verbose) = @_;
   my $ir  = {};
 
-  _file_checking($file);
+  Gears::Util->file_checking($file);
   open my $fh, '<', $file;
   my $line = <$fh>;
 
@@ -63,26 +63,21 @@
       next;
     }
     next if ($line =~ /^\s+$/);
-    next if ($line =~ m[//|}]);
+    next if ($line =~ m[^//]);
+    next if ($line =~ m[^\}\s*$ir->{name};]);
 
     if ($line =~ m|__code (\w+)\(([()\.\*\s\w,_]+)\)|) {
-      unless ($code_verbose) {
-        push(@{$ir->{codes}},$1);
-        next;
-      }
-      push(@{$ir->{codes}}, [$1,$2]);
-      next;
+      $line = "enum Code $1;\n";
     }
 
-    $line =~ s/\s*([\w\s\*]+);\s*/$1/;
-    push(@{$ir->{data}},$1);
+    push(@{$ir->{content}},$line);
   }
 
   return $ir;
 }
 
-sub _file_checking {
-  my $file_name = shift;
+sub file_checking {
+  my ($class, $file_name) = @_;
   unless (-f $file_name) {
     croak "invalid filepath :$file_name\n";
   }
@@ -116,4 +111,41 @@
   return $header_file;
 }
 
+sub find_headers_path {
+  my $class = shift;
+  my $find_path = shift // ".";
+
+  my @files;
+  find( { wanted => sub { push @files, $_ if /\.h/ }, no_chdir => 1 }, $find_path);
+
+  return \@files;
+}
+
+sub h2context_str {
+  my ($class, $h2context) = @_;
+  my $context = '';
+  my $space = '    ';
+
+  $context =  "${space}struct $h2context->{name} {\n";
+  my $content_space;
+  if (exists $h2context->{content}){
+    my @chars = split //, $h2context->{content}->[0];
+    for my $w (@chars) {
+      last if ($w !~ /\s/);
+      $content_space .= $w;
+    }
+  }
+
+  unless (defined $content_space) {
+    $content_space = "";
+  }
+
+  for my $c (@{$h2context->{content}}) {
+    $c =~ s/$content_space//;
+    $context .= "${space}${space}$c";
+  }
+  $context .= "${space}} $h2context->{name};\n";
+  return $context;
+}
+
 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plautogen/impl/SingleLinkedStack.h	Wed Nov 27 21:21:42 2019 +0900
@@ -0,0 +1,26 @@
+typedef struct SingleLinkedStack<Type, Isa> impl Stack {
+  struct Element* top;
+} SingleLinkedStack;
+
+/*
+    // Stack Interface
+    struct Stack {
+        union Data* stack;
+        union Data* data;
+        union Data* data1;
+        enum Code whenEmpty;
+        enum Code clear;
+        enum Code push;
+        enum Code pop;
+        enum Code pop2;
+        enum Code isEmpty;
+        enum Code get;
+        enum Code get2;
+        enum Code next;
+    } Stack;
+    // Stack implementations
+    struct SingleLinkedStack {
+        struct Element* top;
+    } SingleLinkedStack;
+    */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plautogen/interface/Meta.h	Wed Nov 27 21:21:42 2019 +0900
@@ -0,0 +1,6 @@
+typedef struct Meta <Type, Impl> {
+  enum DataType type;
+  long size;
+  long len;
+  struct Queue* wait; // tasks waiting this dataGear;
+} Meta;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plautogen/interface/Stack.h	Wed Nov 27 21:21:42 2019 +0900
@@ -0,0 +1,17 @@
+typedef struct Stack<Type, Impl>{
+        union Data* stack;
+        union Data* data;
+        union Data* data1;
+        /* Type* stack; */
+        /* Type* data; */
+        /* Type* data1; */
+        __code whenEmpty(...);
+        __code clear(Impl* stack,__code next(...));
+        __code push(Impl* stack,Type* data, __code next(...));
+        __code pop(Impl* stack, __code next(Type* data, ...));
+        __code pop2(Impl* stack, __code next(Type* data, Type* data1, ...));
+        __code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...));
+        __code get(Impl* stack, __code next(Type* data, ...));
+        __code get2(Impl* stack, __code next(Type* data, Type* data1, ...));
+        __code next(...);
+} Stack;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plautogen/interface/UInteger.h	Wed Nov 27 21:21:42 2019 +0900
@@ -0,0 +1,3 @@
+typedef struct UInteger<Impl> {
+    unsigned int value;
+} UInteger;