/* * Copyright (C) 2005, Robert Geist, Jacob Hicks, Mark Smotherman, James Westall * All rights reserved. * * cg_petri_pb2.c: Cg/OpenGL program to simulate non-timed Petri nets (or timed * nets where all firing times are fixed to a single constant) using floating * point pbuffers. * * gcc -L/usr/lib -L/usr/X11R6/lib cg_petri_pb2.c -lpthread -lglut -lGLU -lGL * -lCg -lCgGL -lXmu -lXi -lXext -lX11 -o cg_petri_pb2 * * cg_petri_pb2 whatever.dat 2> catch_err * */ #include #include #include #include #include #include #include #include #include "cg_petri_pb2.h" /* * texture storage and codes therein: * * place texture: token count * reservation texture: token reservation count (per place) * transition texture: enabled or not * * incidence textures (2D): * height width * t_inputp[transition][iplace]: for each transition, a list of * input places * * p_inputt[place][itransition]: for each place, a list of * input transitions * * p_outputt[place][otransition]: for each place, a list of * output transitions */ float t_inputp[TRANSITIONS*MAX_T_IN_DEGREE]; float p_inputt[PLACES*MAX_P_IN_DEGREE]; float p_outputt[PLACES*MAX_P_OUT_DEGREE]; /* * the top index in each of these is used for a dummy node to * rectangularize the tests in the Cg part and thereby avoid * conditionals; the dummy place (index PLACES-1) will have a * large supply of tokens so that it will never be over-subscribed * and never interfere with any enabling ; the dummy transition * (index TRANSITIONS-1) will never be enabled * * the only catch here is to remember to declare (in .h) 1 more * than you need; there is no longer any power-of-2 restriction */ float places[PLACES]; float reservations[PLACES]; float transitions[TRANSITIONS]; void set_token_count(int place,int count) { places[place] = (float)(count); } void init_places() { int i; for(i=0;i0) scratch_op[over_sub++] = i; } if(over_sub){ /* * we have conflicts, and resolution isn't easy; first, * we'll need the list of enabled transitions */ glReadPixels(0,0,TRANSITIONS-1,1,GL_RED,GL_FLOAT,transitions); do { /* select at random from over-subcribed place list */ sopi = (int)(over_sub*genrand()); pi = scratch_op[sopi]; /* * build scratch list of enabled transitions that want * tokens from this place; but, we only want those * enabled transitions that carry a maximal number of * over-subscribed input places, so that disabling one * will give us the largest possible reduction in * over-subscriptions; so, restart the list whenever * we find a larger value */ sc=0; top_count=0; for(j=0;j places[npi]){ osip_count++; } } if(osip_counttop_count){ top_count=osip_count; sc=0; } scratch_ct[sc++] = ti; } } /* zap excess entries from this scratch list */ disable = (int)(reservations[pi]) - (int)(places[pi]); while(disable--){ zap = (int)(sc*genrand()); ti = scratch_ct[zap]; transitions[ti] = 0; for(sffl=zap+1;sffl0) scratch_op[new_over_sub++] = pi; } } while(over_sub=new_over_sub); /* changed those enabled, so write it back out */ glBindTexture(GL_TEXTURE_RECTANGLE_NV,6); glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV,0,0,0, TRANSITIONS,1,GL_RED,GL_FLOAT,transitions); } write_places(1); /* reload the dummy place for next pass */ set_token_count(PLACES-1,TRANSITIONS-1); /* * readback places here, instead of the top of the loop, * because they're written during FIRE, and so, on the * first pass, the array versions are correct but the pixel * versions are not (still (0.8,0.7,0.6)) */ glReadPixels(0,2,PLACES-1,1,GL_RED,GL_FLOAT,places); } } void MyError(CGcontext mycontext) { int lastError = cgGetError(); if(lastError){ printf("%s\n",cgGetErrorString(lastError)); printf("%s\n", cgGetLastListing(mycontext)); exit(0); } } void do_cg() { CGcontext context; CGprofile fragment_profile; int i; context = cgCreateContext(); if(cgGLIsProfileSupported(CG_PROFILE_FP30)) { fragment_profile=CG_PROFILE_FP30; fprintf(stderr, "Cg fragment profile fp30 supported.\n"); } else { fprintf(stderr,"No soup for you!\n"); exit(1); } for(i=0;i<3;i++){ fp[i] = cgCreateProgramFromFile(context,CG_SOURCE,"cg_petri_pb2.cg", fragment_profile,fpname[i],NULL); MyError(context); cgGLLoadProgram(fp[i]); } cgGLEnableProfile(fragment_profile); } struct timeval stampS, stampE; void start_timer() { gettimeofday(&stampS, NULL); } void end_timer() { gettimeofday(&stampE, NULL); printf("seconds: %d\n",stampE.tv_sec - stampS.tv_sec); } int vattrib[] = { GLX_DRAWABLE_TYPE_SGIX,GLX_PBUFFER_BIT_SGIX, GLX_RENDER_TYPE_SGIX,GLX_RGBA_BIT_SGIX, GLX_RED_SIZE,32, GLX_BUFFER_SIZE,32, GLX_X_RENDERABLE_SGIX,False, None}; int pbattrib[] = { GLX_PRESERVED_CONTENTS_SGIX, GLX_LARGEST_PBUFFER_SGIX, None}; int main(int argc, char **argv) { Display *display; int screen; int count; GLXFBConfigSGIX *config; GLXPbuffer glx_pbuffer; GLXContext pb_ctx; if((display=XOpenDisplay(NULL))==NULL){ fprintf(stderr,"can't open\n"); exit(1); } screen = DefaultScreen(display); config = (GLXFBConfigSGIX *)glXChooseFBConfigSGIX(display,screen, vattrib,&count); glx_pbuffer = glXCreateGLXPbufferSGIX(display,*config,MAX_TRANSITIONS_PLACES, 3,pbattrib); pb_ctx = (GLXContext)glXCreateContextWithConfigSGIX(display,*config, GLX_RGBA_TYPE_SGIX,NULL,True); glXMakeCurrent(display,glx_pbuffer,pb_ctx); start_timer(); init_textures(argv[1]); do_cg(); load_textures_onto_card(); draw(); end_timer(); }