Beispiel #1
0
Datei: mem.c Projekt: apwan06/sim
bool_t diff_reg(mem_t oldr, mem_t newr, FILE *outfile)
{
    word_t pos;
    int len = oldr->len;
    bool_t diff = FALSE;
    if (newr->len < len)
    len = newr->len;
    //write back
    if(oldr->ca) oldr->ca->clear(TRUE);
    if(newr->ca) newr->ca->clear(TRUE);

    for (pos = 0; (!diff || outfile) && pos < len; pos += 4) {
        word_t ov = 0;
        word_t nv = 0;
    oldr->getWord(pos, &ov);
    newr->getWord(pos, &nv);
    if (nv != ov) {
        diff = TRUE;
        if (outfile)
        fprintf(outfile, "%s:\t0x%.8x\t0x%.8x\n",
            reg_table[pos/4].name, ov, nv);
    }
    }
    return diff;
}
Beispiel #2
0
Datei: mem.c Projekt: apwan06/sim
bool_t diff_mem(mem_t oldm, mem_t newm, FILE *outfile)
{
    word_t pos;
    int len = oldm->len;
    bool_t diff = FALSE;
    if (newm->len < len)
    len = newm->len;

    // write back
    if(oldm->ca) oldm->ca->clear(TRUE);
    if(newm->ca) newm->ca->clear(TRUE);

    //remove bus
    /*
    if(oldm->bus) oldm->bus->remove(oldm);
    if(newm->bus) newm->bus->remove(newm);
    */


    for (pos = 0; (!diff || outfile) && pos+4 <= len; pos += 4) {
        word_t ov = 0;  word_t nv = 0;
        oldm->getWord(pos, &ov);
        newm->getWord(pos, &nv);
        if (nv != ov) {
            diff = TRUE;
            if (outfile)
                fprintf(outfile, "0x%.4x:\t0x%.8x\t0x%.8x\n", pos, ov, nv);
        }
    }
    //return *oldm->m != *newm->m;
    return diff;
}
Beispiel #3
0
    void pinnedFree(T *ptr)
    {
        mem_iter iter = pinned_maps.find((void *)ptr);

        if (iter != pinned_maps.end()) {
            iter->second.is_free = true;
            pinned_used_bytes -= iter->second.bytes;
        } else {
            pinnedFreeWrapper(ptr); // Free it because we are not sure what the size is
        }
    }
Beispiel #4
0
	virtual void solve(int nt) final
	{   
          // multiple calls to sovlve() are meant to advance the solution by nt
          nt += timestep;

          // being generous about out-of-loop barriers 
          if (timestep == 0)
          {
	    mem->barrier();
#if !defined(NDEBUG)
	    hook_ante_loop_called = false;
#endif
	    hook_ante_loop(nt);
	    mem->barrier();
          }

          // moved here so that if an exception is thrown from hook_ante_loop these do not cause complaints
#if !defined(NDEBUG)
	  hook_ante_step_called = false;
	  hook_post_step_called = false;
#endif

	  while (timestep < nt)
	  {   
	    // progress-bar info through thread name (check top -H)
	    monitor(float(timestep) / nt);  // TODO: does this value make sanse with repeated advence() calls?

            // might be used to implement multi-threaded signal handling
            mem->barrier();
            if (mem->panic) break;

            // proper solver stuff
            hook_ante_step();

	    for (int e = 0; e < n_eqns; ++e) scale(e, ct_params_t::hint_scale(e));

	    for (int e = 0; e < n_eqns; ++e) xchng(e);
	    for (int e = 0; e < n_eqns; ++e) 
            { 
              advop(e);
              if (e != n_eqns - 1) mem->barrier();
            }
	    for (int e = 0; e < n_eqns; ++e) cycle(e); // note: cycle assumes ascending loop index

	    for (int e = 0; e < n_eqns; ++e) scale(e, -ct_params_t::hint_scale(e));

            timestep++;
            hook_post_step();
	  }   

          mem->barrier();
          // note: hook_post_loop was removed as conficling with multiple-advance()-call logic
        }
Beispiel #5
0
    void pinnedGarbageCollect()
    {
        for(mem_iter iter = pinned_maps.begin(); iter != pinned_maps.end(); ++iter) {
            if ((iter->second).is_free) {
                pinnedFreeWrapper(iter->first);
            }
        }

        mem_iter memory_curr = pinned_maps.begin();
        mem_iter memory_end  = pinned_maps.end();

        while(memory_curr != memory_end) {
            if (memory_curr->second.is_free) {
                pinned_maps.erase(memory_curr++);
            } else {
                ++memory_curr;
            }
        }
    }
Beispiel #6
0
    T* pinnedAlloc(const size_t &elements)
    {
        managerInit();
        T* ptr = NULL;
        // Allocate the higher megabyte. Overhead of creating pinned memory is
        // more so we want more resuable memory.
        size_t alloc_bytes = divup(sizeof(T) * elements, 1048576) * 1048576;

        if (elements > 0) {

            // FIXME: Add better checks for garbage collection
            // Perhaps look at total memory available as a metric
            if (pinned_maps.size() >= MAX_BUFFERS || pinned_used_bytes >= MAX_BYTES) {
                pinnedGarbageCollect();
            }

            for(mem_iter iter = pinned_maps.begin();
                iter != pinned_maps.end(); ++iter) {

                mem_info info = iter->second;
                if (info.is_free && info.bytes == alloc_bytes) {
                    iter->second.is_free = false;
                    pinned_used_bytes += alloc_bytes;
                    return (T *)iter->first;
                }
            }

            // Perform garbage collection if memory can not be allocated
            if (cudaMallocHost((void **)&ptr, alloc_bytes) != cudaSuccess) {
                pinnedGarbageCollect();
                CUDA_CHECK(cudaMallocHost((void **)(&ptr), alloc_bytes));
            }

            mem_info info = {false, false, alloc_bytes};
            pinned_maps[ptr] = info;
            pinned_used_bytes += alloc_bytes;
        }
        return (T*)ptr;
    }
Beispiel #7
0
Datei: mem.c Projekt: apwan06/sim
/*  CACHE  */
CacheRec::CacheRec(mem_t target, int b, int s, int E, int t):
    cb(b),cB(1<<b),cs(s),cS(1<<s),cE(E),ct(t),nlines(E<<s){
    len = target->getLen();
    tm = target;
    contents = new byte_t[nlines<<b];
    valid = new bool_t[nlines];
    dirty = new bool_t[nlines];
    tags = new byte_t[nlines];
    clear();
#ifdef CHECK_CACHE
    checker = copy_mem(target);
#else
    checker = NULL;
#endif
}
Beispiel #8
0
	virtual void cycle(int e) final
	{ 
	  n[e] = (n[e] + 1) % n_tlev - n_tlev;  // -n_tlev so that n+1 does not give out of bounds
          if (e == n_eqns - 1) mem->cycle(rank); 
	}
Beispiel #9
0
bool exec( int instruction )
{
//    printf( "EXEC: %d\n", instruction );

    switch( instruction )
    {
    // moo
    case 0:
        {
            if( prog_pos == program.begin() )
                quit( true );

            prog_pos--;	// skip previous command.
            int level = 1;
            while( level > 0 )
            {
                if( prog_pos == program.begin() )
                    break;

                prog_pos--;
            
                if( (*prog_pos) == 0 )
                    level++;
                else
                if( (*prog_pos) == 7 )  // look for MOO
                    level--;
            }

            if( level != 0 )
                quit(true);

            return exec( *prog_pos );
        }
    
    // mOo
    case 1:
        if( mem_poses[stomach] == memory[stomach].begin() )
            quit( true );
        else
            mem_poses[stomach]--;
        break;

    // moO
    case 2:
        mem_poses[stomach]++;
        if( mem_poses[stomach] == memory[stomach].end() )
        {
            memory[stomach].push_back(0);
            mem_poses[stomach] = memory[stomach].end();
            mem_poses[stomach]--;
        }
        break;
    
    // mOO    
    case 3:
        if( (*mem_poses[stomach]) == 3 )
            quit( false );
        return exec(*mem_poses[stomach]);
    
    // Moo
    case 4:
        if( (*mem_poses[stomach]) != 0 )
            printf( "%c", *mem_poses[stomach] );
        else
        {
            (*mem_poses[stomach]) = getchar();
            while( getchar() != '\n' );
        }
        break;
    
    // MOo
    case 5:
        (*mem_poses[stomach])--;
        break;
    
    // MoO
    case 6:
        (*mem_poses[stomach])++;
        break;

    // MOO
    case 7:
        if( (*mem_poses[stomach]) == 0 )
        {
            int level = 1;
            int prev = 0;
            prog_pos++;	  // have to skip past next command when looking for next moo.
            if( prog_pos == program.end() )
                break;
            while( level > 0 )
            {
                prev = *prog_pos;
                prog_pos++;
                
                if( prog_pos == program.end() )
                    break;
                
                if( (*prog_pos) == 7 )
                    level++;
                else
                if( (*prog_pos) == 0 )	// look for moo command.
                {
                    level--;
                    if( prev == 7 )
                        level--;
                }
            }
            if( level != 0 )
                quit( true );
        }
        break;
    
    // OOO
    case 8:
        (*mem_poses[stomach]) = 0;
        break;

    // MMM
    case 9:
        if( has_register_val )
            (*mem_poses[stomach]) = register_val;
        else
            register_val = (*mem_poses[stomach]);
        has_register_val = !has_register_val;
        break;

    // OOM
    case 10:
        printf( "%d\n", *mem_poses[stomach] );
        break;
    
    // oom
    case 11:
        {
            char buf[100];
            unsigned int c = 0;
            while( c < sizeof(buf)-1 )
            {
                buf[c] = getchar();
                c++;
                buf[c] = 0;
                
                if( buf[c-1] == '\n' )
                    break;
            }
            // swallow, just in case.
            if( c == sizeof(buf) )
                while( getchar() != '\n' );
            
            (*mem_poses[stomach]) = atoi( buf );

            break;
        }

    // MMm
    case 12:
        {
            stomach--; if(stomach < 0) stomach += num_stomachs;
            break;
        }

    // MmM
    case 13:
        {
            stomach++; if(stomach >= num_stomachs) stomach -= num_stomachs;
            break;
        }

    // Oom
    case 14:
        {
            for( int i=0; i<num_stomachs; ++i )
            {
                if( mem_poses[i] == memory[i].begin() )
                    quit( true );
                else
                    mem_poses[i]--;
            }
            break;
        }

    // oOm
    case 15:
        {
            for( int i=0; i<num_stomachs; ++i )
            {
                mem_poses[i]++;
                if( mem_poses[i] == memory[i].end() )
                {
                    memory[i].push_back(0);
                    mem_poses[i] = memory[i].end();
                    mem_poses[i]--;
                }
            }
            break;
        }
    
    // OoM
    case 16:
        {
            for( int i=0; i<num_stomachs; ++i )
            {
                (*mem_poses[i])--;
            }
            break;
        }

    // oOM
    case 17:
        {
            for( int i=0; i<num_stomachs; ++i)
            {
                (*mem_poses[i])++;
            }
            break;
        }

    // ooo
    case 18:
        {
            for( int i=0; i<num_stomachs; ++i)
            {
                (*mem_poses[i]) = 0;
            }
            break;
        }

    // mmm
    case 19:
        {
            if( has_register_val )
            {
                int weight = 0;
                for( int i=0; i<num_stomachs; ++i)
                {
                    if( *mem_poses[i] > 0 )
                        weight += *mem_poses[i];
                }
                if( weight == 0 )
                {
                    for( int i=0; i<num_stomachs; ++i )
                    {
                        *mem_poses[i] = register_val;
                    }
                } else {
                    int div = register_val / weight;
                    int mod = register_val - div * weight;
                    for( int i=0; i<num_stomachs; ++i )
                    {
                        if( *mem_poses[i] > 0 )
                            *mem_poses[i] = *mem_poses[i] * div;
                        else if( *mem_poses[i] < 0 )
                            *mem_poses[i] = mod * -*mem_poses[i];
                        else
                            *mem_poses[i] = 0;
                    }
                }
            } else {
                int sum = 0;
                for( int i=0; i<num_stomachs; ++i)
                {
                    sum += *mem_poses[i];
                }
                register_val = sum;
            }
            has_register_val = !has_register_val;
            break;
        }

    // bad stuff
    default:
        quit( false );
    };

    prog_pos++;

    return true;
}
Beispiel #10
0
int main( int argc, char** argv )
{
	if( argc < 2 )
	{
		printf( "Usage: %s program.cow\n\n", argv[0] );
		exit( 1 );
	}

	FILE* f = fopen( argv[1], "rb" );

	if( f == NULL )
	{
		printf( "Cannot open source file [%s].\n", argv[1] );
        exit( 1 );
	}

    char buf[3];
    memset( buf, 0, 3 );
    //int pos = 0; // tola: unused?

    while( !feof(f) )
    {
        int found = 0;
        buf[2] = fgetc( f );

        if(( found = !strncmp( "moo", buf, 3 ) ))
            program.push_back( 0 );
        else if(( found = !strncmp( "mOo", buf, 3 ) ))
            program.push_back( 1 );
        else if(( found = !strncmp( "moO", buf, 3 ) ))
            program.push_back( 2 );
        else if(( found = !strncmp( "mOO", buf, 3 ) ))
            program.push_back( 3 );
        else if(( found = !strncmp( "Moo", buf, 3 ) ))
            program.push_back( 4 );
        else if(( found = !strncmp( "MOo", buf, 3 ) ))
            program.push_back( 5 );
        else if(( found = !strncmp( "MoO", buf, 3 ) ))
            program.push_back( 6 );
        else if(( found = !strncmp( "MOO", buf, 3 ) ))
            program.push_back( 7 );
        else if(( found = !strncmp( "OOO", buf, 3 ) ))
            program.push_back( 8 );
        else if(( found = !strncmp( "MMM", buf, 3 ) ))
            program.push_back( 9 );
        else if(( found = !strncmp( "OOM", buf, 3 ) ))
            program.push_back( 10 );
        else if(( found = !strncmp( "oom", buf, 3 ) ))
            program.push_back( 11 );
        // from here down,  distributed digestion specific calls
        else if(( found = !strncmp( "MMm", buf, 3 ) ))
            program.push_back( 12 );
        else if(( found = !strncmp( "MmM", buf, 3 ) ))
            program.push_back( 13 );
        else if(( found = !strncmp( "Oom", buf, 3 ) ))
            program.push_back( 14 );
        else if(( found = !strncmp( "oOm", buf, 3 ) ))
            program.push_back( 15 );
        else if(( found = !strncmp( "OoM", buf, 3 ) ))
            program.push_back( 16 );
        else if(( found = !strncmp( "oOM", buf, 3 ) ))
            program.push_back( 17 );
        else if(( found = !strncmp( "ooo", buf, 3 ) ))
            program.push_back( 18 );
        else if(( found = !strncmp( "mmm", buf, 3 ) ))
            program.push_back( 19 );
            
        if( found )
        {
            memset( buf, 0, 3 );
        }
        else
        {
            buf[0] = buf[1];
            buf[1] = buf[2];
            buf[2] = 0;
        }
    }

	fclose( f );

	printf( "Welcome to COW!\n\nExecuting [%s]...\n\n", argv[1] );

    // init main memory.
    for(int i=0; i<num_stomachs; ++i)
    {
        memory[i].push_back(0);
        mem_poses[i] = memory[i].begin();
    }
    stomach = 0;

    prog_pos = program.begin();
    while( prog_pos != program.end() )
        if( !exec( *prog_pos ) )
            break;

    quit( false );

	return 0;
}
Beispiel #11
0
bool compile( int instruction, bool advance )
{
    switch( instruction )
    {
    // moo
    case 0:
        {
            int level = 1;
            int num = MOOcount + 1;
            mem_t::iterator t = prog_pos;

            t--;   // skip past previous command when searching for MOO.
            if( t != program.begin() )
            {
                if((*t) == 7 )
                    num--;

                while( level > 0 )
                {
                    if( t == program.begin() )
                        break;

                    t--;
            
                    if( (*t) == 0 )
                        level++;
                    else
                    if( (*t) == 7 )  // look for MOO
                    {
                        level--;
                        num--;
                    }
                }
            }
            if( level != 0 && advance )
                quit();
            else if( level != 0 )
            {
                fprintf( output, "rterr();" );
                break;
            }

            moocount++;
            fprintf( output, "goto M%d;", num );
            fprintf( output, "m%d:", moocount );
            PRETTY( "moo" );
        }
        break;

    
    // mOo
    case 1:
        fprintf( output, "if(p==m.begin()){rterr();}else{p--;}" );
        PRETTY( "mOo" );
        break;

    // moO
    case 2:
        fprintf( output, "p++; if(p==m.end()){m.push_back(0);p=m.end();p--;}" );
        PRETTY( "moO" );
        break;
    
    // mOO    
    case 3:
        // I think it should be possible to build a switch statement here and then
        // use the compile function itself to fill in the possibilities.
//        printf( "NOT IMPLEMENTED: mOO\n\n" );
//        quit();
        fprintf( output, "switch(*p){" );
        fprintf( output, "case 0:{" ); compile( 0, false ); fprintf( output, "}break;" );
        fprintf( output, "case 1:{" ); compile( 1, false ); fprintf( output, "}break;" );
        fprintf( output, "case 2:{" ); compile( 2, false ); fprintf( output, "}break;" );
        fprintf( output, "case 4:{" ); compile( 4, false ); fprintf( output, "}break;" );
        fprintf( output, "case 5:{" ); compile( 5, false ); fprintf( output, "}break;" );
        fprintf( output, "case 6:{" ); compile( 6, false ); fprintf( output, "}break;" );
        fprintf( output, "case 7:{" ); compile( 7, false ); fprintf( output, "}break;" );
        fprintf( output, "case 8:{" ); compile( 8, false ); fprintf( output, "}break;" );
        fprintf( output, "case 9:{" ); compile( 9, false ); fprintf( output, "}break;" );
        fprintf( output, "case 10:{" ); compile( 10, false ); fprintf( output, "}break;" );
        fprintf( output, "case 11:{" ); compile( 11, false ); fprintf( output, "}break;" );
        fprintf( output, "default:{goto x;}};" );
        PRETTY( "mOO" );
        break;
    
    // Moo
    case 4:
        fprintf( output, "if((*p)!=0){putchar(*p);}else{(*p)=getchar();while(getchar()!='\\n');}" );
        PRETTY( "Moo" );
        break;
    
    // MOo
    case 5:
        fprintf( output, "(*p)--;" );
        PRETTY( "MOo" );
        break;
    
    // MoO
    case 6:
        fprintf( output, "(*p)++;" );
        PRETTY( "MoO" );
        break;

    // MOO
    case 7:
        {
            int level = 1;
            int num = moocount;
            int prev = 0;
            mem_t::iterator t = prog_pos;
            t++;	  // have to skip past next command when looking for next moo.

            if( t != program.end() )
            {
                if( (*t) == 0 )
                    num++;

                while( level > 0 )
                {
                    prev = *t;
                    t++;
                
                    if( t == program.end() )
                        break;
                
                    if( (*t) == 7 ) // look for MOO command.
                        level++;
                    else
                    if( (*t) == 0 )	// look for moo command.
                    {
                        if( prev == 7 )
                            level--;
                
                        level--;
                        num++;
                    }
                
                    if( level == 0 )
                        break;
                }
            }
            if( advance && level != 0 )
                quit();
            else if( level != 0 )
            {
                fprintf( output, "rterr();" );
                break;
            }
            
            MOOcount++;
            fprintf( output, "M%d:", MOOcount );
            fprintf( output, "if(!(*p))goto m%d;", num );
            PRETTY( "MOO" );
        }
        break;
    
    // OOO
    case 8:
        fprintf( output, "(*p)=0;" );
        PRETTY( "OOO" );
        break;

    // MMM
    case 9:
        fprintf( output, "if(h){(*p)=r;}else{r=(*p);}h=!h;" );
        PRETTY( "MMM" );
        break;

    // OOM
    case 10:
        fprintf( output, "printf(\"%%d\\n\",*p);" );
        PRETTY( "OOM" );
        break;
    
    // oom
    case 11:
        fprintf( output, "char b[100];int c=0;" );
        fprintf( output, "while(c<sizeof(b)-1){b[c]=getchar();c++;b[c]=0;if(b[c-1]=='\\n')break;}" );
        fprintf( output, "if(c==sizeof(b))while(getchar()!='\\n');(*p)=atoi(b);" );
        PRETTY( "oom" );
        break;

    // bad stuff
    default:
        return false;
    };

    if( advance )
        prog_pos++;

    return true;
}
Beispiel #12
0
int main( int argc, char** argv )
{
	if( argc < 2 )
	{
		printf( "Usage: %s program.cow\n\n", argv[0] );
		exit( 1 );
	}

	FILE* f = fopen( argv[1], "rb" );

	if( f == NULL )
	{
		printf( "Cannot open source file [%s].\n", argv[1] );
        exit( 1 );
	}

    char buf[3];
    memset( buf, 0, 3 );
    int pos = 0;

    while( !feof(f) )
    {
        int found = 0;
        buf[2] = fgetc( f );

        if( found = !strncmp( "moo", buf, 3 ) )
            program.push_back( 0 );
        else if( found = !strncmp( "mOo", buf, 3 ) )
            program.push_back( 1 );
        else if( found = !strncmp( "moO", buf, 3 ) )
            program.push_back( 2 );
        else if( found = !strncmp( "mOO", buf, 3 ) )
            program.push_back( 3 );
        else if( found = !strncmp( "Moo", buf, 3 ) )
            program.push_back( 4 );
        else if( found = !strncmp( "MOo", buf, 3 ) )
            program.push_back( 5 );
        else if( found = !strncmp( "MoO", buf, 3 ) )
            program.push_back( 6 );
        else if( found = !strncmp( "MOO", buf, 3 ) )
            program.push_back( 7 );
        else if( found = !strncmp( "OOO", buf, 3 ) )
            program.push_back( 8 );
        else if( found = !strncmp( "MMM", buf, 3 ) )
            program.push_back( 9 );
        else if( found = !strncmp( "OOM", buf, 3 ) )
            program.push_back( 10 );
        else if( found = !strncmp( "oom", buf, 3 ) )
            program.push_back( 11 );
            
        if( found )
        {
            memset( buf, 0, 3 );
        }
        else
        {
            buf[0] = buf[1];
            buf[1] = buf[2];
            buf[2] = 0;
        }
    }

	fclose( f );

	printf( "Compiling [%s]...\n", argv[1] );

    // init main memory.
    /*
    memory.push_back( 0 );
    mem_pos = memory.begin();
    */
    
    output = fopen( "cow.out.cpp", "wb" );
    fprintf( output, "#include <stdio.h>\n" );
    fprintf( output, "#include <vector>\n" );
    fprintf( output, "typedef std::vector<int> t_;t_ m;t_::iterator p;\n" );
    fprintf( output, "bool h;int r;\n" );
    fprintf( output, "void rterr(){puts(\"Runtime error.\\n\");}\n" );
    fprintf( output, "int main(int a,char** v){\n" );
    fprintf( output, "m.push_back(0);p=m.begin();h=false;\n" );

    prog_pos = program.begin();
    while( prog_pos != program.end() )
        if( !compile( *prog_pos, true ) )
        {
            printf( "ERROR!\n" );
            break;
        }
        
    fprintf( output, "x:return(0);}\n" );        
    fclose( output );

    printf( "C++ source code: cow.out.cpp\n" );

    #ifdef COMPILER
        std::string path( (const char*)COMPILER );
        path.append( " " );
        path.append( (const char*)NAME_FLAG );
        path.append( " " );
        path.append( (const char*)OUTPUT_EXEC );
        path.append( " " );
        path.append( (const char*)FLAGS );
        path.append( " " );
        path.append( (const char*)OUTPUT_CPP );
        if( system( path.c_str() ) )
            printf( "\n\nCould not compile.  Possible causes:  C++ compiler is not installed, not in path, or not named '%s' or there is a bug in this compiler.\n\n", COMPILER );
        else
            printf( "Executable created: cow.out\n" );
    #endif

	return 0;
}
bool op_ring::execute()
{
    if( pos != 0 ) switch( pos )
    {
        // One
        case 2:
            value=1;
            break;

        // Zero
        case 3:
            value=0;
            break;

        // Load
        case 4:
            value=*mem_pos;
            break;

        // Store
        case 5:
            *mem_pos = value;
            break;

        // DAdd
        case 7:
            {
                int t = mem_pos - memory.begin();
                t += value;
                if( t < 0 )
                    return false;   // out of bounds!
                if( t < memory.size() )
                    mem_pos = memory.begin() + t;
                else
                {
                    while( memory.size() <= t )
                        memory.push_back(0);
                    mem_pos = memory.begin() + t;
                }
            }
            break;

        // Logic
        case 8:
            if( *mem_pos != 0 )
                value = value && 1;
            else
                value = 0;
            break;

        // If
        case 9:
            if( *mem_pos == 0 )
                break;
            // else fall through!

        // PAdd
        case 6:
            {
                int t = prog_pos - program.begin();
                t += value;
                if( t < 0 || t >= program.size() )
                    return false;   // out of bounds!
                prog_pos = program.begin() + t;
                next_instruction = false;
            }
            break;

        // IntIO
        case 10:
            if( value == 0 )
            {
                // read integer
                char buf[100];
                int c = 0;
                while( c < sizeof(buf)-1 )
                { 
                    buf[c] = getchar();
                    c++;
                    buf[c] = 0;
            
                    if( buf[c-1] == '\n' )
                        break;
                }
                // swallow, just in case.
                if( c == sizeof(buf) )
                    while( getchar() != '\n' );
        
                (*mem_pos) = atoi( buf );
            }
            else
                printf( "%d", *mem_pos );
            break;
        
        // AscIO
        case 11:
            if( value == 0 )
            {
                // read character
                (*mem_pos) = getchar();
                while( getchar() != '\n' );
            }
            else
                printf( "%c", *mem_pos );
            break;

        // Exit
        case 1:
        default:
            return false;
    }

    return true;
}
int main( int argc, char** argv )
{
	if( argc < 2 )
	{
		printf( "Usage: %s program.wrl\n\n", argv[0] );
		exit( 1 );
	}

	FILE* f = fopen( argv[1], "rb" );

	if( f == NULL )
	{
		printf( "Cannot open source file [%s].\n", argv[1] );
        exit( 1 );
    }

    while( !feof(f) )
    {
        char buf = fgetc( f );
        if( buf == '1' )
            program.push_back( true );
        else if( buf == '0' )
            program.push_back( false );
    }

	fclose( f );

	printf( "Welcome to Whirl!\n\nExecuting [%s]...\n\n", argv[1] );

    // init main memory.
    memory.push_back( 0 );
    mem_pos = memory.begin();

    prog_pos = program.begin();
    bool execute = false;
    while( prog_pos != program.end() )
    {
        next_instruction = true;

        if( *prog_pos )
        {
            cur->rotate();
            execute = false;
        }
        else
        {
            cur->switch_dir();
            if( execute )
            {
                if( !cur->execute() )
                    return 0;
                (cur == &ops)? cur = &math: cur = &ops;                
                execute = false;
            }
            else
                execute = true;
        }
        
        if( next_instruction )
            prog_pos++;
    }

	printf( "\n" );

	return 0;
}