package s_source ; # $Id: s_source.pm 3711 2014-10-28 19:43:54Z alin $ use Exporter (); @ISA = qw(Exporter); @EXPORT = qw(s_source); use strict ; use gte ; use trick_version ; sub s_source($) { my ($sim_ref) = @_ ; my (@cpp_headers , @c_headers) ; #-------------------------------------------------------------- # Generate S_source.c open S_SOURCE, ">S_source.cpp" or die "Couldn't open S_source.cpp!\n"; open S_SOURCE_H, ">S_source.hh" or die "Couldn't open S_source.hh!\n"; # Get Trick version my ($version, $thread) = get_trick_version() ; $thread =~ s/\d+\.// ; #--------------------------- # Get date my $date = localtime ; my ($sec,$min,$hour,$mday,$mon,$year) = localtime ; $year += 1900 ; $mon += 1 ; my ($login) = getpwuid($<) ; #--------------------------- # Print version - date my ($temp) = "Id:" ; printf S_SOURCE "\n/* \$$temp S_source.cpp auto $year/%02d/%02d %02d\:%02d\:%02d $login \$ */\n", $mon , $mday , $hour , $min , $sec ; #--------------------------- # Includes print S_SOURCE_H " /** PURPOSE: (Contains sim ojbects) */ #ifndef __S_SOURCE_HH__ #define __S_SOURCE_HH__ #include #include #include #include \"sim_services/MemoryManager/include/attributes.h\" #include \"sim_services/include/populate_attribute_maps.hh\" #include \"sim_services/SimObject/include/SimObject.hh\" #include \"sim_services/SimObject/include/JobData.hh\" #include \"sim_services/Units/include/UnitsMap.hh\"\n\n" ; # TODO get rid of this statement! This is still here because of the collect print S_SOURCE_H "#define ip_alloc calloc\n" ; print S_SOURCE_H "$$sim_ref{system_headers}\n" ; foreach my $h ( @{$$sim_ref{sim_class_includes}} ) { if ( $h !~ /\.h$/ ) { push @cpp_headers , $h ; } else { my ($full_path) ; $full_path = $$sim_ref{headers_full_path}{$h} ; if ($$sim_ref{headers_lang}{$h} eq "cpp" ) { push @cpp_headers , $h ; } else { push @c_headers , $h ; } } } my %temp_hash ; @cpp_headers = grep ++$temp_hash{$_} < 2, @cpp_headers ; foreach my $h ( sort @cpp_headers ) { my $printed = 0 ; # list header files that are not under the trick_source directory # (e.g. trick_models/ directory) if ( $h !~ s/^TRICK_HOME\/trick_source\/// ) { foreach ( @{$$sim_ref{inc_paths}} ) { if ($h =~ s,^$_/,, ) { print S_SOURCE_H "#include \"$h\"\n"; $printed = 1 ; last ; } } } # list header files that are in trick_source if ( $printed eq 0 ) { print S_SOURCE_H "#include \"$h\"\n"; } } if ( scalar @c_headers ) { print S_SOURCE_H "\n#ifdef __cplusplus\n" , "extern \"C\" {\n" , "#endif\n\n" ; foreach my $h ( sort @c_headers ) { my $printed = 0 ; if ( $h !~ s/^TRICK_HOME\/trick_source\/// ) { foreach ( @{$$sim_ref{inc_paths}} ) { if ($h =~ s,^$_/,, ) { print S_SOURCE_H "#include \"$h\"\n"; $printed = 1 ; last ; } } } if ( $printed eq 0 ) { print S_SOURCE_H "#include \"$h\"\n"; } } print S_SOURCE_H "\n#ifdef __cplusplus\n" , "}\n" , "#endif\n" ; } print S_SOURCE_H "\n" ; # prints the user defined header code print S_SOURCE_H "$$sim_ref{user_header}\n" ; # prints classes defined in S_define file. Set in parse_s_define.pm print S_SOURCE_H $$sim_ref{sim_class_code} ; # prints an instantiation for each templated sim object for ICG to process. print S_SOURCE_H "#ifdef TRICK_ICG\n" ; print S_SOURCE_H $$sim_ref{template_instance_declarations} ; print S_SOURCE_H "#endif\n\n" ; # prints an extern declaration for each sim object print S_SOURCE_H "#ifndef SWIG\n" ; print S_SOURCE_H $$sim_ref{extern_instance_declarations} ; print S_SOURCE_H "#endif\n" ; print S_SOURCE_H "\n\n#endif\n" ; close S_SOURCE_H ; print S_SOURCE "#include \"S_source.hh\"\n" ; print S_SOURCE "$$sim_ref{user_code}\n" ; # prints associated call functions print S_SOURCE $$sim_ref{sim_class_call_functions} ; # prints instantiations from S_define file. Set in parse_s_define.pm print S_SOURCE "\n// Instantiate stuff\n" ; print S_SOURCE $$sim_ref{instance_declarations} ; # prints integration loop sim objects from S_define file print S_SOURCE "\n// Integration Loop Sim Object(s) JMP\n" ; foreach my $integ_loop ( @{$$sim_ref{integ_loop}} ) { print S_SOURCE "IntegLoopSimObject $$integ_loop{name}($$integ_loop{cycle}, $$integ_loop{child}" ; my @integ_loop_sim_objects = split(/\s*,\s*/, $$integ_loop{name_list} ) ; foreach my $integ_loop_sim_obj (@integ_loop_sim_objects) { print S_SOURCE ", &$integ_loop_sim_obj" ; } print S_SOURCE ", (void *)NULL);\n" ; } #--------------------------- # Default Environment print S_SOURCE "\n/* Default Environment */\n" , "SimEnvironment::SimEnvironment() {\n\n" ; print S_SOURCE gte("S_source"); print S_SOURCE "}\n\n" ; #--------------------------- # Memory Init print S_SOURCE "\n/* Memory Init */\n" , "void memory_init( void ) {\n\n" ; print S_SOURCE " " x 4 , "ALLOC_INFO * ai ;\n" ; print S_SOURCE " " x 4 , "exec_set_version_date_tag\( \"@(#)CP Version $version-$thread, $date\" \) ;\n" ; print S_SOURCE " " x 4 , "exec_set_build_date\( \"$date\" \) ;\n" ; print S_SOURCE " " x 4 , "exec_set_current_version\( \"$version-$thread\" \) ;\n\n" ; print S_SOURCE " " x 4 , "populate_sim_services_class_map\(\) ;\n" ; print S_SOURCE " " x 4 , "populate_sim_services_enum_map\(\) ;\n" ; print S_SOURCE " " x 4 , "populate_class_map\(\) ;\n" ; print S_SOURCE " " x 4 , "populate_enum_map\(\) ;\n" ; print S_SOURCE "\n" ; # prints the job class order for the cyclic jobs foreach my $cl ( @{$$sim_ref{user_class_order}} ) { print S_SOURCE" exec_add_scheduled_job_class(\"$cl\") ;\n" ; } print S_SOURCE "\n" ; foreach my $inst ( @{$$sim_ref{instances}} ) { print S_SOURCE " " x 4 , "exec_add_sim_object(&$inst, \"$inst\") ;\n" ; my $temp_type = $$sim_ref{instances_type}{$inst} ; $temp_type =~ s/\s//g ; $temp_type =~ s/[<>,:*]/_/g ; print S_SOURCE " " x 4 , "TMM_declare_ext_var(&$inst, TRICK_STRUCTURED,\"$temp_type\", 0, \"$inst\", 0, NULL) ;\n" ; print S_SOURCE " " x 4 , "if ( (ai = get_alloc_info_at(&$inst)) != NULL ) {\n" ; print S_SOURCE " " x 8 , "ai->alloced_in_memory_init = 1 ;\n" ; print S_SOURCE " " x 4 , "}\n" ; } print S_SOURCE " " x 4 , "// Add Integration Loop Sim Object(s) JMP\n" ; foreach my $integ_loop ( sort sim_integ_by_name @{$$sim_ref{integ_loop}} ) { print S_SOURCE " " x 4 , "exec_add_sim_object(&$$integ_loop{name} , \"$$integ_loop{name}\") ;\n" ; print S_SOURCE " " x 4 , "TMM_declare_ext_var(&$$integ_loop{name}, TRICK_STRUCTURED,\"IntegLoopSimObject\", 0, \"$$integ_loop{name}\", 0, NULL) ;\n" ; } print S_SOURCE "\n" ; print S_SOURCE $$sim_ref{create_connections} ; print S_SOURCE "\n" , " " x 4 , "return ;\n" , "}\n\n" ; #------------------------------------------ # Write out the 'exec_collect_init()' function in S_source.c # # exec_collect_init() is responsible for initializing all the pointer # management associated with 'collect' statements in the S_define file. # # For every collect statement, perform the following: # (I highly recommended viewing S_source.c to get a clearer picture # of what is going on here.) # 1) Get a pointer to the collect info in the CP structures. # 2) Allocate memory for the collect pointer list based on the number # of items listed in the collect statement, allocate an additional # 8 bytes to hold the number of items in the list. # 3) store the address of the new memory in the 'n' parameter. # 4) store the number of items in the list at the address pointed to # by 'n'. # 5) Shift the address f the original allocation past the 8 byte integer # stored at 'n', and save this address in the pointer defined by the # collect statement. This address represents the first element of an # array of addresses of each of the elements listed in the collect list. # 6) Save the address of each element in the collect list in the # respective pointer list just created. # #------------- # Write the exec_collect_init() entry point. print S_SOURCE "\n/*---------------------------------------------------------------------*/\n\n" ; print S_SOURCE "void exec_collect_init( void ) {\n\n" ; if ( exists $$sim_ref{collect} ) { # print S_SOURCE " " x 4 , "long * lp ;\n\n" ; # # # foreach my $collect ( sort sim_collect_by_name @{$$sim_ref{collect}} ) { # # Number of params in collect statement # my $np = $$collect{num_params} ; # # print S_SOURCE " " x 4 , "$$collect{name} = (void**)ip_alloc( $np + 1 , sizeof(void*));\n" , # " " x 4 , "lp = (long *)$$collect{name} ;\n" , # " " x 4 , "*lp = $np ;\n" , # " " x 4 , "$$collect{name}++ ;\n" ; # # for ( my $i = 0; $i < $np ; $i++ ) { # my $name = @{$$collect{params}}[$i] ; # print S_SOURCE " " x 4 , "$$collect{name}\[$i\] = (void*)&($name);\n" ; # } # } #print S_SOURCE "\n#if 0\n" ; foreach my $collect ( @{$$sim_ref{collect}} ) { print S_SOURCE " " x 4 , "$$collect{name} = NULL ;\n" ; my $np = $$collect{num_params} ; foreach my $name ( @{$$collect{params}} ) { print S_SOURCE " " x 4 , "$$collect{name} = add_collect($$collect{name}, (void*)&($name));\n" ; } } #print S_SOURCE "\n#endif\n" ; } if ( exists $$sim_ref{vcollect} ) { foreach my $collect ( sort sim_vcollect_by_name @{$$sim_ref{vcollect}} ) { my $name = $$collect{name} ; my $func = $$collect{constructor} ; undef $func if ( defined $func ) && ( $func eq "" ) ; foreach my $item ( sort @{$$collect{items}} ) { my $ref = $item ; if ( $ref =~ s/&// ) { $ref = "&($ref)" ; } else { $ref = "$ref" ; } if (defined $func ) { $ref = "$func( $ref )" ; } print S_SOURCE " " x 4, "$name.push_back(\n", " " x 24, "$ref );\n" ; } print S_SOURCE "\n" ; } } print S_SOURCE " " x 4, "return ;\n" , "}\n\n" ; close S_SOURCE ; } #-------------------------------------------------------------- # Given an array of sim integrate statements, provide sort routines # sub sim_integ_by_name { return #Sort by sim integrate name in ASCII order ( ${$a}{name} cmp ${$b}{name} ) || #If two names are identical, then sort based on cycle time ( ${$a}{cycle} <=> ${$b}{cycle} ); } #-------------------------------------------------------------- # Given an array of sim collect statements, provide sort routines # sub sim_collect_by_name { return #Sort by sim collect statement name in ASCII order ( ${$a}{name} cmp ${$b}{name} ) || #If two params are identical, then sort based on num_params ( ${$a}{num_params} <=> ${$b}{num_params} ); } #-------------------------------------------------------------- # Given an array of sim Vcollect statements, provide sort routines # sub sim_vcollect_by_name { return #Sort by sim collect statement name in ASCII order ( ${$a}{name} cmp ${$b}{name} ); } 1;