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