00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00045
00046
00047
00048
00049
00050
00051
00053
00054
00055
00056
00057
00058
00059
00060 #include <assert.h>
00061 #include <stdio.h>
00062 #include <unistd.h>
00063 #include <limits.h>
00064 #include <stdarg.h>
00065 #include <string.h>
00066 #include <list>
00067 #include <map>
00068 #include <vector>
00069 #include <stdlib.h>
00070
00071 #include "topcode.h"
00072 #include "targ_isa_properties.h"
00073 #include "targ_isa_subset.h"
00074 #include "targ_isa_operands.h"
00075 #include "gen_util.h"
00076 #include "si_gen.h"
00077
00078 static ISA_SUBSET machine_isa;
00079
00080
00081 const int bits_per_long = 32;
00082 const int bits_per_long_long = 64;
00083 const bool use_long_longs = true;
00084 const int max_operands = ISA_OPERAND_max_operands;
00085 const int max_results = ISA_OPERAND_max_results;
00086
00088 int Mod( int i, int j )
00090
00091
00092
00094 {
00095 int rem;
00096
00097 if ( j == 0 )
00098 return i;
00099
00100 rem = i % j;
00101
00102 if ( rem == 0 )
00103 return 0;
00104
00105 if ( (i < 0) != (j < 0) )
00106 return j + rem;
00107 else
00108 return rem;
00109 }
00110
00112 static void Maybe_Print_Comma(FILE* fd, bool& is_first)
00114
00115
00117 {
00118 if ( is_first )
00119 is_first = false;
00120 else
00121 fprintf(fd,",");
00122 }
00123
00126
00128 class GNAME {
00130
00131
00133 public:
00134 GNAME();
00135
00136 GNAME(char* prefix);
00137
00138 GNAME(GNAME& other);
00139
00140
00141
00142 char* Gname();
00143
00144 char* Addr_Of_Gname();
00145
00146 void Stub_Out();
00147
00148
00149
00150 private:
00151 char gname[16];
00152
00153 bool stubbed;
00154 static int count;
00155 };
00156
00157 int GNAME::count = 0;
00158
00159 GNAME::GNAME() : stubbed(false) {
00160 sprintf(gname,"&gname%d",count++);
00161 }
00162
00163 GNAME::GNAME(char* prefix) : stubbed(false) {
00164 assert(strlen(prefix) <= 8);
00165 sprintf(gname,"&%s%d",prefix,count++);
00166 }
00167
00168 GNAME::GNAME(GNAME& other) : stubbed(false) {
00169 sprintf(gname,"%s",other.gname);
00170 }
00171
00172 char* GNAME::Gname() {
00173 if (stubbed)
00174 return "0";
00175 else
00176 return gname + 1;
00177 }
00178
00179 char* GNAME::Addr_Of_Gname() {
00180 if (stubbed)
00181 return "0";
00182 else
00183 return gname;
00184 }
00185
00186 void GNAME::Stub_Out() {
00187 stubbed = true;
00188 }
00189
00192
00194 class RES_WORD {
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 public:
00219 static void Find_Word_Allocate_Field(int width, int count,
00220 int &word, int &bit);
00221
00222
00223
00224
00225
00226 static void Output_All(FILE* fd);
00227
00228
00229 private:
00230 int bit_inx;
00231 const int word_inx;
00232 long long initializer;
00233 long long overuse_mask;
00234
00235
00236 static std::list<RES_WORD*> res_words;
00237 static int count;
00238 static bool has_long_long_word;
00239
00240
00241 RES_WORD()
00242 : bit_inx(0),
00243 word_inx(count++),
00244 initializer(0),
00245 overuse_mask(0)
00246 {
00247 res_words.push_back(this);
00248 }
00249 bool Allocate_Field(int width, int count, int &word, int &bit);
00250 };
00251
00252 std::list<RES_WORD*> RES_WORD::res_words;
00253 int RES_WORD::count = 0;
00254 bool RES_WORD::has_long_long_word = false;
00255
00257 bool RES_WORD::Allocate_Field(int width, int count, int &word, int &bit)
00259
00260
00261
00263 {
00264 int new_inx = bit_inx + width;
00265
00266 if ( use_long_longs && new_inx >= bits_per_long_long
00267 || !use_long_longs && new_inx >= bits_per_long
00268 ) {
00269 return false;
00270 }
00271
00272 if ( new_inx >= bits_per_long )
00273 has_long_long_word = true;
00274
00275 word = word_inx;
00276 bit = bit_inx;
00277 initializer |= ((1ll << (width - 1)) - (count + 1)) << bit_inx;
00278 overuse_mask |= (1ll << (width - 1)) << bit_inx;
00279 bit_inx += width;
00280 return true;
00281 }
00282
00283 void RES_WORD::Find_Word_Allocate_Field(int width, int count,
00284 int &word, int &bit)
00285 {
00286 std::list<RES_WORD*>::iterator rwi;
00287 for ( rwi = res_words.begin(); rwi != res_words.end(); ++rwi ) {
00288 if ( (*rwi)->Allocate_Field(width,count,word,bit) )
00289 return;
00290 }
00291
00292 RES_WORD* new_res_word = new RES_WORD();
00293
00294 if ( ! new_res_word->Allocate_Field(width,count,word,bit) ) {
00295 fprintf(stderr,"### Cannot allocate field for %d resources\n",count);
00296 exit(EXIT_FAILURE);
00297 }
00298 }
00299
00300 void RES_WORD::Output_All(FILE* fd)
00301 {
00302 if ( count == 0 )
00303 fprintf(stderr,"ERROR: no resource words allocated.\n");
00304 else if ( count > 1 ) {
00305 fprintf(stderr,"ERROR: cannot handle %d > 1 long long worth of "
00306 "resource info.\n",
00307 count);
00308 }
00309 else {
00310
00311
00312 fprintf(fd,"const SI_RRW SI_RRW_initializer = 0x%" LL_FORMAT "x;\n",
00313 res_words.front()->initializer);
00314 fprintf(fd,"const SI_RRW SI_RRW_overuse_mask = 0x%" LL_FORMAT "x;\n",
00315 res_words.front()->overuse_mask);
00316 }
00317 }
00318
00321
00323 class RES {
00325
00327
00328 public:
00329 RES(char *name,int count);
00330
00331
00332
00333 static RES* Get(int id);
00334
00335
00336 char* Name() const { return name; }
00337
00338
00339 char* Addr_Of_Gname() { return gname.Addr_Of_Gname(); }
00340
00341
00342 unsigned int Count() const { return count; }
00343
00344
00345 int Word() const { return word; }
00346
00347
00348
00349 int Id() const { return id; }
00350
00351
00352
00353 unsigned int Shift_Count() const { return shift_count; }
00354
00355
00356 static void Output_All( FILE* fd );
00357
00358
00359 private:
00360 const int count;
00361 char* const name;
00362 GNAME gname;
00363 int word;
00364 int field_width;
00365 int shift_count;
00366
00367 const int id;
00368 static int total;
00369
00370 static std::map<int,RES*> resources;
00371
00372 void Calculate_Field_Width();
00373 void Calculate_Field_Pos();
00374
00375 static void Calculate_Fields();
00376
00377
00378
00379
00380 void Output( FILE* fd );
00381 };
00382
00383 int RES::total = 0;
00384 std::map<int,RES*> RES::resources;
00385
00386 RES::RES(char *name, int count)
00387
00388 : count(count), name(name), id(total++), gname("resource")
00389 {
00390 resources[id] = this;
00391 }
00392
00393 RES* RES::Get(int i)
00394 {
00395 assert(total > 0 && i >= 0 && i < total);
00396 return resources[i];
00397 }
00398
00399 void RES::Output_All( FILE* fd )
00400 {
00401 int i;
00402
00403 Calculate_Fields();
00404
00405 for ( i = 0; i < total; ++i )
00406 resources[i]->Output(fd);
00407
00408 fprintf(fd,"const int SI_resource_count = %d;\n",total);
00409 fprintf(fd,"SI_RESOURCE * const SI_resources[] = {");
00410
00411 bool is_first = true;
00412 for ( i = 0; i < total; ++i ) {
00413 Maybe_Print_Comma(fd,is_first);
00414 fprintf(fd,"\n %s",resources[i]->gname.Addr_Of_Gname());
00415 }
00416
00417 fprintf(fd,"\n};\n");
00418 }
00419
00421 void RES::Calculate_Field_Width()
00423
00424
00426 {
00427 int i;
00428
00429 assert(count > 0);
00430
00431 for ( i = 31 ; i >= 0 ; --i ) {
00432 if ((( (int) 1) << i) & count) {
00433 field_width = i + 2;
00434 break;
00435 }
00436 }
00437 }
00438
00439 void RES::Calculate_Field_Pos()
00440 {
00441 Calculate_Field_Width();
00442 RES_WORD::Find_Word_Allocate_Field(field_width,count,word,shift_count);
00443 }
00444
00446 void RES::Calculate_Fields()
00448
00449
00451 {
00452 for ( int i = 0; i < total; ++i )
00453 resources[i]->Calculate_Field_Pos();
00454 }
00455
00457 void RES::Output( FILE* fd )
00459
00461 {
00462 fprintf(fd,"SI_RESOURCE %s = {\"%s\",%d,%d,%d,%d};\n",
00463 gname.Gname(),
00464 name,
00465 id,
00466 count,
00467 word,
00468 shift_count);
00469 }
00470
00473
00475 class RES_REQ {
00477
00478
00480
00481 public:
00482 RES_REQ();
00483
00484 bool Add_Resource(const RES* res, int cycle);
00485
00486
00487
00488
00489 void Output(FILE* fd);
00490
00491
00492 char* Addr_Of_Gname() { return gname.Addr_Of_Gname(); }
00493
00494
00495 char* Gname() { return gname.Gname(); }
00496
00497
00498 bool Compute_Maybe_Output_II_RES_REQ(int ii, FILE* fd,
00499 GNAME*& res_req_gname,
00500 GNAME*& resource_id_set_gname );
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 int Max_Res_Cycle() { return max_res_cycle; }
00513
00514
00515
00516
00517 void Compute_Output_Resource_Count_Vec(FILE* fd);
00518
00519
00520
00521 char* Res_Count_Vec_Gname() { return res_count_vec_gname.Gname(); }
00522
00523
00524 int Res_Count_Vec_Size() const { return res_count_vec_size; }
00525
00526
00527 char* Res_Id_Set_Gname() { return res_id_set_gname.Gname(); }
00528
00529
00530
00531 private:
00532
00534 class CYCLE_RES {
00536
00537
00538
00540
00541 public:
00542 CYCLE_RES(int cycle, const RES* res) : cycle(cycle), res_id(res->Id()) {}
00543
00544
00545 int Cycle() const { return cycle; }
00546
00547
00548 RES* Res() const { return RES::Get(res_id); }
00549
00550
00551 friend bool operator < (const CYCLE_RES a, const CYCLE_RES b)
00552
00553 {
00554 return a.cycle< b.cycle
00555 || a.cycle == b.cycle && a.res_id < b.res_id;
00556 }
00557
00558 CYCLE_RES()
00559
00560 : cycle(0), res_id(0)
00561 {
00562 fprintf(stderr,"### Default initializer for CYCLE_RES"
00563 " shouldn't happen.\n");
00564 }
00565
00566 private:
00567 const short cycle;
00568 const short res_id;
00569 };
00570
00571 typedef std::map< CYCLE_RES,int,std::less <CYCLE_RES> > CYCLE_RES_COUNT_MAP;
00572
00573
00574
00575 int max_res_cycle;
00576
00577
00578 CYCLE_RES_COUNT_MAP cycle_res_count;
00579
00580
00581 GNAME gname;
00582
00583
00584 GNAME res_count_vec_gname;
00585
00586
00587 GNAME res_id_set_gname;
00588
00589
00590 int res_count_vec_size;
00591
00592
00593 bool Compute_II_RES_REQ(int ii, RES_REQ& ii_res_req);
00594 };
00595
00596 RES_REQ::RES_REQ()
00597 : max_res_cycle(-1),
00598 gname("res_req")
00599 {}
00600
00601 bool RES_REQ::Add_Resource(const RES* res, int cycle)
00602 {
00603 assert(cycle >= 0);
00604 if ( cycle > max_res_cycle ) max_res_cycle = cycle;
00605
00606 CYCLE_RES cr = CYCLE_RES(cycle,res);
00607 int count = cycle_res_count[cr];
00608
00609 if ( count >= res->Count() )
00610 return false;
00611
00612 cycle_res_count[cr] = ++count;
00613 return true;
00614 }
00615
00617 bool RES_REQ::Compute_II_RES_REQ(int ii, RES_REQ& ii_res_req)
00619
00620
00621
00623 {
00624 CYCLE_RES_COUNT_MAP::iterator mi;
00625 for (mi = cycle_res_count.begin(); mi != cycle_res_count.end(); ++mi) {
00626 int cycle = (*mi).first.Cycle();
00627 RES* res = (*mi).first.Res();
00628 int count = (*mi).second;
00629
00630 for (int i = 0; i < count; ++i) {
00631 if ( ! ii_res_req.Add_Resource(res,Mod(cycle,ii)) )
00632 return false;
00633 }
00634 }
00635
00636 return true;
00637 }
00638
00639 bool RES_REQ::Compute_Maybe_Output_II_RES_REQ(int ii, FILE* fd,
00640 GNAME*& res_req_gname,
00641 GNAME*& res_id_set_gname_ref )
00642 {
00643 RES_REQ ii_res_req;
00644
00645 if ( ! Compute_II_RES_REQ(ii,ii_res_req) )
00646 return false;
00647
00648 ii_res_req.Output(fd);
00649 res_req_gname = new GNAME(ii_res_req.gname);
00650 res_id_set_gname_ref = new GNAME(ii_res_req.res_id_set_gname);
00651 return true;
00652 }
00653
00654 void RES_REQ::Compute_Output_Resource_Count_Vec(FILE* fd)
00655 {
00656 CYCLE_RES_COUNT_MAP::iterator mi;
00657 std::map<int,int,std::less<int> > res_inx_count;
00658
00659
00660 for (mi = cycle_res_count.begin(); mi != cycle_res_count.end(); ++mi) {
00661 RES* res = (*mi).first.Res();
00662 int count = (*mi).second;
00663
00664 res_inx_count[res->Id()] += count;
00665 }
00666
00667 res_count_vec_size = res_inx_count.size();
00668
00669 if ( res_count_vec_size == 0 ) {
00670 res_count_vec_gname.Stub_Out();
00671 return;
00672 }
00673
00674
00675 fprintf(fd,"static SI_RESOURCE_TOTAL %s[] = {",
00676 res_count_vec_gname.Gname());
00677
00678 bool is_first = true;
00679 std::map<int,int,std::less<int> >::iterator mj;
00680 for (mj = res_inx_count.begin(); mj != res_inx_count.end(); ++mj) {
00681 RES* res = RES::Get((*mj).first);
00682 int count = (*mj).second;
00683
00684 Maybe_Print_Comma(fd,is_first);
00685 fprintf(fd,"\n {%s,%d} /* %s */",
00686 RES::Get(res->Id())->Addr_Of_Gname(),count,res->Name());
00687 }
00688 fprintf(fd,"\n};\n");
00689 }
00690
00691 void RES_REQ::Output(FILE* fd)
00692 {
00693 int i;
00694 CYCLE_RES_COUNT_MAP::iterator mi;
00695 std::vector<unsigned long long> res_vec((size_t) max_res_cycle + 1,0);
00696 std::vector<unsigned long long> res_used_set((size_t) max_res_cycle + 1,0);
00697
00698 for (mi = cycle_res_count.begin(); mi != cycle_res_count.end(); ++mi) {
00699 int cycle = (*mi).first.Cycle();
00700 RES* res = (*mi).first.Res();
00701 long long count = (*mi).second;
00702
00703 res_vec[cycle] += count << res->Shift_Count();
00704 res_used_set[cycle] |= 1ll << res->Id();
00705 }
00706
00707 fprintf(fd,"static const SI_RRW %s[] = {\n %d",
00708 gname.Gname(),
00709 max_res_cycle + 1);
00710
00711 for ( i = 0; i <= max_res_cycle; ++i )
00712 fprintf(fd,",\n 0x%" LL_FORMAT "x",res_vec[i]);
00713
00714 fprintf(fd,"\n};\n");
00715
00716 if ( max_res_cycle < 0 ) {
00717 res_id_set_gname.Stub_Out();
00718 return;
00719 }
00720
00721 fprintf(fd,"static const SI_RESOURCE_ID_SET %s[] = {",
00722 res_id_set_gname.Gname());
00723
00724 bool is_first = true;
00725 for ( i = 0; i <= max_res_cycle; ++i ) {
00726 Maybe_Print_Comma(fd,is_first);
00727 fprintf(fd,"\n 0x%" LL_FORMAT "x",res_used_set[i]);
00728 }
00729
00730 fprintf(fd,"\n};\n");
00731 }
00732
00735
00737 class ISLOT {
00739
00740
00741
00743
00744 public:
00745 ISLOT(char* name, int skew, int avail_count);
00746
00747
00748
00749 char* Addr_Of_Gname() { return gname.Addr_Of_Gname(); }
00750
00751
00752 static int Count() { return count; }
00753
00754
00755 static void Output_All(FILE* fd);
00756
00757
00758 private:
00759 char* const name;
00760 const int skew;
00761 const int avail_count;
00762 GNAME gname;
00763 static std::list<ISLOT*> islots;
00764 static int count;
00765 };
00766
00767 std::list<ISLOT*> ISLOT::islots;
00768 int ISLOT::count = 0;
00769
00770 ISLOT::ISLOT(char* name, int skew, int avail_count)
00771 : name(name),
00772 skew(skew),
00773 avail_count(avail_count)
00774 {
00775 islots.push_back(this);
00776 ++count;
00777 }
00778
00779 void ISLOT::Output_All(FILE* fd)
00780 {
00781 std::list<ISLOT*>::iterator isi;
00782
00783 fprintf(fd,"const int SI_issue_slot_count = %d;\n",count);
00784
00785 for ( isi = islots.begin(); isi != islots.end(); ++isi ) {
00786 ISLOT* islot = *isi;
00787 fprintf(fd,"static SI_ISSUE_SLOT %s = { \"%s\",%d,%d};\n",
00788 islot->gname.Gname(),
00789 islot->name,
00790 islot->skew,
00791 islot->avail_count);
00792 }
00793
00794 if ( count == 0 )
00795 fprintf(fd,"SI_ISSUE_SLOT * const SI_issue_slots[1] = {0};\n");
00796 else {
00797 fprintf(fd,"SI_ISSUE_SLOT * const SI_issue_slots[%d] = {",count);
00798
00799 bool is_first = true;
00800 for ( isi = islots.begin(); isi != islots.end(); ++isi ) {
00801 ISLOT* islot = *isi;
00802 Maybe_Print_Comma(fd,is_first);
00803 fprintf(fd,"\n %s",islot->Addr_Of_Gname());
00804 }
00805
00806 fprintf(fd,"\n};\n");
00807 }
00808 }
00809
00812
00814 class LATENCY_INFO {
00816
00817
00819
00820 public:
00821 LATENCY_INFO(int max_elements);
00822
00823
00824 void Set_Any_Time(int time);
00825
00826
00827
00828 void Set_Time(int index, int time);
00829
00830
00831 void Output(FILE* fd);
00832
00833
00834 char* Gname() { return gname.Gname(); }
00835
00836
00837 private:
00838 GNAME gname;
00839 const int max_elements;
00840 bool any_time_defined;
00841 int any_time;
00842 std::vector<bool> times_defined;
00843 std::vector<int> times;
00844 };
00845
00846 LATENCY_INFO::LATENCY_INFO(int max_elements)
00847 : gname("latency"),
00848 max_elements(max_elements),
00849 any_time_defined(false),
00850 times_defined(max_elements,false),
00851 times(max_elements)
00852 {}
00853
00854 void LATENCY_INFO::Set_Any_Time(int time)
00855 {
00856 if ( any_time_defined ) {
00857 fprintf(stderr,"### Warning any_time redefined for %s. "
00858 "Was %d. Is %d\n",
00859 gname.Gname(),
00860 any_time,
00861 time);
00862 }
00863
00864 any_time_defined = true;
00865 any_time = time;
00866 }
00867
00868 void LATENCY_INFO::Set_Time(int index, int time)
00869 {
00870 if ( any_time_defined ) {
00871 fprintf(stderr,"### WARNING: %s setting specific time after any time. "
00872 "Any %d. Specific %d\n",
00873 gname.Gname(),
00874 any_time,
00875 time);
00876 }
00877
00878 assert(index < max_elements);
00879
00880 if ( times_defined[index] ) {
00881 fprintf(stderr,"### WARNING: Resetting %s time. "
00882 "Was %d. Now is %d\n",
00883 gname.Gname(),
00884 time,
00885 times[index]);
00886 }
00887
00888 times_defined[index] = true;
00889 times[index] = time;
00890 }
00891
00892 void LATENCY_INFO::Output(FILE* fd)
00893 {
00894 fprintf(fd,"static const mUINT8 %s[] = {",gname.Gname());
00895
00896 bool is_first = true;
00897 std::vector<int>::iterator i;
00898 for ( i = times.begin(); i < times.end(); ++i ) {
00899 Maybe_Print_Comma(fd,is_first);
00900 fprintf(fd,"%d",any_time_defined ? any_time : *i);
00901 }
00902
00903 fprintf(fd,"};\n");
00904 }
00905
00908
00910 class INSTRUCTION_GROUP {
00912
00913
00915
00916 public:
00917
00918 INSTRUCTION_GROUP(char* name);
00919 void Set_Any_Operand_Access_Time(int time);
00920 void Set_Operand_Access_Time(int operand_index, int time);
00921 void Set_Any_Result_Available_Time(int time);
00922 void Set_Result_Available_Time(int result_index, int time);
00923 void Set_Load_Access_Time( int time );
00924 void Set_Last_Issue_Cycle( int time );
00925 void Set_Store_Available_Time( int time );
00926 void Add_Resource_Requirement(const RES* res, int cycle);
00927 #if defined(TARG_SL)
00928 void Add_Alternative_Resource_Requirement(const RES*res, int cycle);
00929 #endif
00930 void Add_Valid_ISLOT(ISLOT* islot);
00931 void Set_Write_Write_Interlock();
00932
00933 static void Output_All(FILE* fd);
00934
00935
00936 char* Addr_Of_Gname() { return gname.Addr_Of_Gname(); }
00937
00938
00939 private:
00940 int id;
00941 GNAME gname;
00942 char* const name;
00943 RES_REQ res_requirement;
00944 #if defined(TARG_SL)
00945 RES_REQ alternative_res_requirement;
00946 #endif
00947
00948 std::list<ISLOT*> valid_islots;
00949 GNAME islot_vec_gname;
00950
00951 LATENCY_INFO operand_latency_info;
00952 LATENCY_INFO result_latency_info;
00953
00954 int load_access_time;
00955 int last_issue_cycle;
00956 int store_available_time;
00957
00958
00959 bool write_write_interlock;
00960
00961 GNAME ii_res_req_gname;
00962
00963
00964
00965 GNAME ii_res_id_set_gname;
00966
00967
00968
00969 unsigned long long bad_iis[2];
00970
00971
00972
00973
00974 static std::list<INSTRUCTION_GROUP*> instruction_groups;
00975
00976
00977 static int count;
00978
00979
00980 int II_Info_Size() { return res_requirement.Max_Res_Cycle(); }
00981
00982
00983 void Output_II_Info(FILE* fd);
00984 void Output_Latency_Info(FILE* fd);
00985 void Output_Issue_Slot_Info(FILE* fd);
00986 void Output(FILE* fd);
00987 };
00988
00989
00990 std::list<INSTRUCTION_GROUP*> INSTRUCTION_GROUP::instruction_groups;
00991 int INSTRUCTION_GROUP::count = 0;
00992
00993 INSTRUCTION_GROUP::INSTRUCTION_GROUP(char* name)
00994 : id(count++),
00995 name(name),
00996 operand_latency_info(max_operands),
00997 result_latency_info(max_results),
00998 load_access_time(0),
00999 last_issue_cycle(0),
01000 store_available_time(0),
01001 write_write_interlock(false),
01002 ii_res_req_gname("ii_rr")
01003 {
01004 bad_iis[0] = 0;
01005 bad_iis[1] = 0;
01006 instruction_groups.push_back(this);
01007 }
01008
01009 void INSTRUCTION_GROUP::Set_Any_Operand_Access_Time(int time)
01010 {
01011 operand_latency_info.Set_Any_Time(time);
01012 }
01013
01014 void INSTRUCTION_GROUP::Set_Operand_Access_Time(int operand_index, int time)
01015 {
01016 operand_latency_info.Set_Time(operand_index,time);
01017 }
01018
01019 void INSTRUCTION_GROUP::Set_Any_Result_Available_Time(int time)
01020 {
01021 result_latency_info.Set_Any_Time(time);
01022 }
01023
01024 void INSTRUCTION_GROUP::Set_Result_Available_Time(int result_index, int time)
01025 {
01026 result_latency_info.Set_Time(result_index,time);
01027 }
01028
01029 void INSTRUCTION_GROUP::Set_Load_Access_Time( int time )
01030 {
01031 load_access_time = time;
01032 }
01033
01034 void INSTRUCTION_GROUP::Set_Last_Issue_Cycle( int time )
01035 {
01036 last_issue_cycle = time;
01037 }
01038
01039 void INSTRUCTION_GROUP::Set_Store_Available_Time( int time )
01040 {
01041 store_available_time = time;
01042 }
01043
01044 void INSTRUCTION_GROUP::Add_Resource_Requirement(const RES* res, int cycle)
01045 {
01046 if (! res_requirement.Add_Resource(res,cycle)) {
01047 fprintf(stderr,"### ERROR: Impossible resource request for "
01048 "instruction group %s.\n",
01049 name);
01050 fprintf(stderr,"### %s at cycle %d.\n",res->Name(),cycle);
01051 }
01052 }
01053
01054 #if defined(TARG_SL)
01055 void INSTRUCTION_GROUP::Add_Alternative_Resource_Requirement(const RES* res, int cycle)
01056 {
01057 if (! alternative_res_requirement.Add_Resource(res,cycle)) {
01058 fprintf(stderr,"### ERROR: Impossible resource request for "
01059 "instruction group %s.\n",
01060 name);
01061 fprintf(stderr,"### %s at cycle %d.\n",res->Name(),cycle);
01062 }
01063 }
01064 #endif
01065
01066 void INSTRUCTION_GROUP::Add_Valid_ISLOT(ISLOT* islot)
01067 {
01068 valid_islots.push_back(islot);
01069 }
01070
01071 void INSTRUCTION_GROUP::Set_Write_Write_Interlock()
01072 {
01073 write_write_interlock = true;
01074 }
01075
01076 void INSTRUCTION_GROUP::Output_II_Info(FILE* fd)
01077 {
01078 int i;
01079 bool is_first;
01080 const int ii_vec_size = II_Info_Size();
01081 const int max_num_bad_iis = sizeof(bad_iis) * 8;
01082
01083
01084
01085
01086 if ( ii_vec_size <= 0 ) {
01087 ii_res_req_gname.Stub_Out();
01088 ii_res_id_set_gname.Stub_Out();
01089 return;
01090 }
01091
01092 std::vector<GNAME*> ii_res_req_gname_vector(ii_vec_size);
01093 std::vector<GNAME*> ii_resources_used_gname_vector(ii_vec_size);
01094 std::vector<bool> ii_can_do_vector(ii_vec_size);
01095
01096 int greatest_bad_ii = 0;
01097
01098 for ( i = 0; i < res_requirement.Max_Res_Cycle(); ++i ) {
01099 if ( res_requirement.Compute_Maybe_Output_II_RES_REQ(
01100 i+1,fd,
01101 ii_res_req_gname_vector[i],
01102 ii_resources_used_gname_vector[i])
01103 ) {
01104 ii_can_do_vector[i] = true;
01105 }
01106 else {
01107 ii_can_do_vector[i] = false;
01108 greatest_bad_ii = i;
01109 if ( i > max_num_bad_iis ) {
01110 fprintf(stderr,"### Error: bad II %d > %d. "
01111 "Need a more flexible representation.\n",
01112 i, max_num_bad_iis);
01113 }
01114 }
01115 }
01116
01117 for ( i = 0; i < sizeof(bad_iis) / sizeof(bad_iis[0]); ++i ) {
01118 bad_iis[i] = 0ULL;
01119 }
01120
01121 for ( i = 0; i <= greatest_bad_ii; ++i ) {
01122 if ( ! ii_can_do_vector[i] ) {
01123 bad_iis[i / bits_per_long_long] |= (1ULL << (i % bits_per_long_long));
01124 }
01125 }
01126
01127
01128
01129 fprintf(fd,"static const SI_RR %s[] = {",
01130 ii_res_req_gname.Gname());
01131
01132 is_first = true;
01133 for ( i = 0; i < ii_vec_size; ++i ) {
01134 Maybe_Print_Comma(fd,is_first);
01135 if ( ii_can_do_vector[i] )
01136 fprintf(fd,"\n %s",ii_res_req_gname_vector[i]->Gname());
01137 else
01138 fprintf(fd,"\n 0");
01139 }
01140
01141 fprintf(fd,"\n};\n");
01142
01143
01144
01145 fprintf(fd,"static const SI_RESOURCE_ID_SET * const %s[] = {",
01146 ii_res_id_set_gname.Gname());
01147
01148 is_first = true;
01149 for ( i = 0; i < ii_vec_size; ++i ) {
01150 Maybe_Print_Comma(fd,is_first);
01151 if ( ii_can_do_vector[i] ) {
01152 fprintf(fd,"\n %s",
01153 ii_resources_used_gname_vector[i]->Gname());
01154 }
01155 else
01156 fprintf(fd,"\n 0");
01157 }
01158
01159 fprintf(fd,"\n};\n");
01160
01161 }
01162
01163 void INSTRUCTION_GROUP::Output_Latency_Info(FILE* fd)
01164 {
01165 operand_latency_info.Output(fd);
01166 result_latency_info.Output(fd);
01167 }
01168
01169 void INSTRUCTION_GROUP::Output_Issue_Slot_Info(FILE* fd)
01170 {
01171 if ( valid_islots.size() == 0 ) {
01172
01173
01174
01175
01176
01177
01178
01179 islot_vec_gname.Stub_Out();
01180 return;
01181 }
01182
01183 fprintf(fd,"static SI_ISSUE_SLOT * const %s[] = {",islot_vec_gname.Gname());
01184
01185 bool is_first = true;
01186 std::list<ISLOT*>::iterator i;
01187 for (i = valid_islots.begin(); i != valid_islots.end(); ++i) {
01188 ISLOT* islot = *i;
01189
01190 Maybe_Print_Comma(fd,is_first);
01191 fprintf(fd,"\n %s",islot->Addr_Of_Gname());
01192 }
01193
01194 fprintf(fd,"\n};\n");
01195 }
01196
01197 void INSTRUCTION_GROUP::Output(FILE* fd)
01198 {
01199 int i;
01200
01201 fprintf(fd,"\n/* Instruction group %s */\n",name);
01202 res_requirement.Output(fd);
01203 res_requirement.Compute_Output_Resource_Count_Vec(fd);
01204 #if defined(TARG_SL)
01205 alternative_res_requirement.Output(fd);
01206 alternative_res_requirement.Compute_Output_Resource_Count_Vec(fd);
01207 #endif
01208 Output_II_Info(fd);
01209 Output_Latency_Info(fd);
01210 Output_Issue_Slot_Info(fd);
01211
01212
01213 fprintf(fd,"static SI %s = {\n",gname.Gname());
01214 fprintf(fd," \"%s\",\n",name);
01215 fprintf(fd," %-15d, /* id */\n",id);
01216 fprintf(fd," %-15s, /* operand latency */\n",
01217 operand_latency_info.Gname());
01218 fprintf(fd," %-15s, /* result latency */\n",
01219 result_latency_info.Gname());
01220 fprintf(fd," %-15d, /* load access time */\n",
01221 load_access_time);
01222 fprintf(fd," %-15d, /* last issue cycle */\n",
01223 last_issue_cycle);
01224 fprintf(fd," %-15d, /* store available time */\n",
01225 store_available_time);
01226 fprintf(fd," %-15s, /* resource requirement */\n",
01227 res_requirement.Gname());
01228 #if defined(TARG_SL)
01229 fprintf(fd, " %-15s, /* alternative resource requirement*/ \n",
01230 alternative_res_requirement.Gname());
01231 #endif
01232 fprintf(fd," %-15s, /* res id used set vec */\n",
01233 res_requirement.Res_Id_Set_Gname());
01234 fprintf(fd," %-15d, /* II info size */\n",
01235 II_Info_Size() >= 0 ? II_Info_Size() : 0);
01236 fprintf(fd," %-15s, /* II resource requirement vec */\n",
01237 ii_res_req_gname.Gname());
01238 fprintf(fd," %-15s, /* II res id used set vec */\n",
01239 ii_res_id_set_gname.Gname());
01240 fprintf(fd," {{");
01241 for ( i = 0; i < sizeof(bad_iis) / sizeof(bad_iis[0]); ++i ) {
01242 fprintf(fd, "0x%" LL_FORMAT "x", bad_iis[i]);
01243 if ( i < sizeof(bad_iis) / sizeof(bad_iis[0]) - 1 ) fprintf(fd, ",");
01244 }
01245 fprintf(fd, "}} , /* Bad IIs */\n");
01246 fprintf(fd," %-15d, /* valid issue slots vec size */\n",
01247 (unsigned int) valid_islots.size());
01248 fprintf(fd," %-15s, /* valid issue slots vec */\n",
01249 islot_vec_gname.Gname());
01250 fprintf(fd," %-15d, /* resource count vec size */\n",
01251 res_requirement.Res_Count_Vec_Size());
01252 fprintf(fd," %-15s, /* resource count vec */\n",
01253 res_requirement.Res_Count_Vec_Gname());
01254 fprintf(fd," %-15s /* write-write interlock */\n",
01255 write_write_interlock ? "1" : "0");
01256 fprintf(fd,"};\n");
01257 }
01258
01259 void INSTRUCTION_GROUP::Output_All(FILE* fd)
01260 {
01261 std::list<INSTRUCTION_GROUP*>::iterator iig;
01262
01263 for (iig = instruction_groups.begin();
01264 iig != instruction_groups.end();
01265 ++iig
01266 ) {
01267 (*iig)->Output(fd);
01268 }
01269
01270 fprintf(fd,"SI * const SI_ID_si[] = {");
01271
01272 bool is_first = true;
01273 for (iig = instruction_groups.begin();
01274 iig != instruction_groups.end();
01275 ++iig
01276 ) {
01277 Maybe_Print_Comma(fd,is_first);
01278 fprintf(fd,"\n %s",(*iig)->Addr_Of_Gname());
01279 }
01280
01281 fprintf(fd,"\n};\n");
01282
01283 fprintf(fd,"const int SI_ID_count = %d;\n",count);
01284
01285 fprintf(fd,"\n");
01286
01287 }
01288
01291
01293 class TOP_SCHED_INFO_MAP {
01295
01296
01298
01299 public:
01300 static void Add_Entry( TOP top, INSTRUCTION_GROUP* ig );
01301
01302
01303 static void Output( FILE* fd );
01304
01305
01306 static void Create_Dummies( void );
01307
01308
01309 private:
01310 static std::vector<char*> top_sched_info_ptr_map;
01311 static std::vector<bool> top_sched_info_defined;
01312 };
01313
01314 std::vector<char*> TOP_SCHED_INFO_MAP::top_sched_info_ptr_map(TOP_count,"0");
01315 std::vector<bool> TOP_SCHED_INFO_MAP::top_sched_info_defined(TOP_count,false);
01316
01317 void TOP_SCHED_INFO_MAP::Create_Dummies( void )
01318 {
01319 INSTRUCTION_GROUP *dummies = NULL;
01320
01321 for ( int i = 0; i < TOP_count; ++i ) {
01322 if ( TOP_is_dummy((TOP)i) ) {
01323 if ( !dummies ) {
01324 dummies = new INSTRUCTION_GROUP("Dummy instructions");
01325 dummies->Set_Any_Operand_Access_Time(0);
01326 dummies->Set_Any_Result_Available_Time(0);
01327 }
01328 top_sched_info_ptr_map[i] = dummies->Addr_Of_Gname();
01329 }
01330 }
01331 }
01332
01333 void TOP_SCHED_INFO_MAP::Add_Entry( TOP top, INSTRUCTION_GROUP* ig )
01334 {
01335 if ( top_sched_info_defined[(int) top] ) {
01336 fprintf(stderr,"### Warning: scheduling information for %s redefined.\n",
01337 TOP_Name(top));
01338 }
01339
01340 top_sched_info_ptr_map[(int) top] = ig->Addr_Of_Gname();
01341 top_sched_info_defined[(int) top] = true;
01342 }
01343
01344 void TOP_SCHED_INFO_MAP::Output( FILE* fd )
01345 {
01346 int i;
01347
01348 fprintf(fd,"SI * const SI_top_si[%d] = {",TOP_count);
01349
01350 bool err = false;
01351 bool is_first = true;
01352 for ( i = 0; i < TOP_count; ++i ) {
01353 bool isa_member = ISA_SUBSET_Member(machine_isa, (TOP)i);
01354 bool is_dummy = TOP_is_dummy((TOP)i);
01355
01356 Maybe_Print_Comma(fd,is_first);
01357
01358 fprintf(fd,"\n %-10s /* %s */",top_sched_info_ptr_map[i],
01359 TOP_Name((TOP)i));
01360
01361 if ( top_sched_info_defined[i] ) {
01362 if ( ! isa_member ) {
01363 fprintf(stderr,"### Warning: scheduling info for non-%s ISA opcode %s\n",
01364 ISA_SUBSET_Name(machine_isa), TOP_Name((TOP)i));
01365 } else if ( is_dummy ) {
01366 fprintf(stderr,"### Warning: scheduling info for dummy opcode %s\n",
01367 TOP_Name((TOP)i));
01368 }
01369 } else {
01370 if ( isa_member && ! is_dummy ) {
01371 fprintf(stderr,"### Error: no scheduling info for opcode %s\n",
01372 TOP_Name((TOP)i));
01373 err = true;
01374 }
01375 }
01376 }
01377 fprintf(fd,"\n};\n");
01378 if (err) exit(EXIT_FAILURE);
01379 }
01380
01383
01384
01385
01386 static INSTRUCTION_GROUP* current_instruction_group;
01387
01388
01389 void Machine(char* name, ISA_SUBSET isa, int argc, char** argv)
01390 {
01391 machine_isa = isa;
01392
01393 TOP_SCHED_INFO_MAP::Create_Dummies();
01394 }
01395
01396 RESOURCE RESOURCE_Create(char* name, int count)
01397 {
01398 return new RES(name,count);
01399 }
01400
01401 ISSUE_SLOT ISSUE_SLOT_Create(char* name, int skew, int count)
01402 {
01403 return new ISLOT(name,skew,count);
01404 }
01405
01406 void Instruction_Group(char* name,...)
01407 {
01408 va_list ap;
01409 TOP opcode;
01410
01411 current_instruction_group = new INSTRUCTION_GROUP(name);
01412
01413 va_start(ap,name);
01414
01415 while ( (opcode = static_cast<TOP>(va_arg(ap,int))) != TOP_UNDEFINED )
01416 TOP_SCHED_INFO_MAP::Add_Entry(opcode,current_instruction_group);
01417
01418 va_end(ap);
01419 }
01420
01421 void Any_Operand_Access_Time( int time )
01422 {
01423 current_instruction_group->Set_Any_Operand_Access_Time(time);
01424 }
01425
01426 void Operand_Access_Time( int operand_index, int time )
01427 {
01428 current_instruction_group->Set_Operand_Access_Time(operand_index,time);
01429 }
01430
01431 void Any_Result_Available_Time( int time )
01432 {
01433 current_instruction_group->Set_Any_Result_Available_Time(time);
01434 }
01435
01436 void Result_Available_Time( int result_index, int time )
01437 {
01438 current_instruction_group->Set_Result_Available_Time(result_index,time);
01439 }
01440
01441 void Load_Access_Time( int time )
01442 {
01443 current_instruction_group->Set_Load_Access_Time(time);
01444 }
01445
01446 void Last_Issue_Cycle( int time )
01447 {
01448 current_instruction_group->Set_Last_Issue_Cycle(time);
01449 }
01450
01451 void Store_Available_Time( int time )
01452 {
01453 current_instruction_group->Set_Store_Available_Time(time);
01454 }
01455
01456 void Resource_Requirement( RESOURCE resource, int time )
01457 {
01458 current_instruction_group->Add_Resource_Requirement(resource,time);
01459 }
01460
01461 #if defined(TARG_SL)
01462 void Alternative_Resource_Requirement( RESOURCE resource, int time )
01463 {
01464 current_instruction_group->Add_Alternative_Resource_Requirement(resource,time);
01465 }
01466 #endif
01467
01468 void Valid_Issue_Slot( ISSUE_SLOT slot )
01469 {
01470 current_instruction_group->Add_Valid_ISLOT(slot);
01471 }
01472
01473 void Write_Write_Interlock()
01474 {
01475 current_instruction_group->Set_Write_Write_Interlock();
01476 }
01477
01478 void Machine_Done( char* filename )
01479 {
01480 FILE* fd = fopen(filename,"w");
01481
01482 char so_name[40];
01483
01484 if ( fd == NULL ) {
01485 fprintf(stderr,"### Error: couldn't write %s\n",filename);
01486 return;
01487 }
01488
01489 fprintf(fd,"#include \"ti_si_types.h\"\n");
01490 RES::Output_All(fd);
01491 RES_WORD::Output_All(fd);
01492 ISLOT::Output_All(fd);
01493 INSTRUCTION_GROUP::Output_All(fd);
01494 TOP_SCHED_INFO_MAP::Output(fd);
01495
01496
01497
01498
01499
01500 strcpy (so_name, filename);
01501 so_name[strlen(filename)-1] = '\0';
01502 fprintf (fd,"const char * sanity_check_targ_so_name = \"%sso\";\n", so_name);
01503
01504 fclose(fd);
01505 }