Mercurial > hg > Members > innparusu > xv6-rpi
diff src/gearsTools/generate_context.pl @ 44:94ca6db2ee9c
add perl script
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 02 Mar 2019 21:05:26 +0900 |
parents | |
children | 9647d79fe97e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gearsTools/generate_context.pl Sat Mar 02 21:05:26 2019 +0900 @@ -0,0 +1,225 @@ +#!/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* 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 +# 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); +getopts('o:d:h'); + +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; + +# 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 *\* *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 .= " context->code[C_${code}] = ${code}_stub;\n"; + } + + my $data_num = keys(%dataGear); + $data_num++; +my $context_c = << "EOFEOF"; +#include <stdlib.h> + +#include "../context.h" + +void initContext(struct Context* context) { + context->heapLimit = sizeof(union Data)*ALLOCATE_SIZE; + context->code = (__code(**) (struct Context*)) NEWN(ALLOCATE_SIZE, void*); + context->data = NEWN(ALLOCATE_SIZE, union Data*); + context->heapStart = NEWN(context->heapLimit, char); + context->heap = context->heapStart; + // context->codeNum = Exit; + +$code_init + +#include "dataGearInit.c" + 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* context, enum Code next) { + // printf("meta %d\\n",next); + if (context->task == NULL) { + goto (context->code[next])(context); + } + context->task = NULL; + context->taskList = NULL; + goto (context->code[Gearef(context, TaskManager)->taskManager->TaskManager.spawnTasks])(context); +} + +__code start_code(struct Context* context) { + goto meta(context, context->next); +} + +__code start_code_stub(struct Context* context) { + goto start_code(context); +} + +__code exit_code(struct Context* context) { + free(context->code); + free(context->data); + free(context->heapStart); + goto exit(0); +} + +__code exit_code_stub(struct Context* context) { + goto exit_code(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(context, ${data});\n"; +} +} + +# end