From 0bcce7d390a812f8c16dba8925653826c34b8e8e Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Mon, 20 Nov 1995 04:05:36 +0000 Subject: [PATCH] speed up search for free function unit slightly. --- sim/ppc/ChangeLog | 28 +++++++++--- sim/ppc/ppc-instructions | 97 +++++++++++++++++++++++++++++++++------- 2 files changed, 102 insertions(+), 23 deletions(-) diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog index 19730da3abc..72d86eb4e1f 100644 --- a/sim/ppc/ChangeLog +++ b/sim/ppc/ChangeLog @@ -1,5 +1,15 @@ +Sun Nov 19 23:00:52 1995 Michael Meissner + + * ppc-instructions (model data, model_busy): Rather than using a + bit mask for the busy units, just use a char array. Also, only + support 2 function units an insn can use, rather than a loop. + Fri Nov 17 14:08:08 1995 Michael Meissner + * table.c (table_entry_read): Move setting entry->line_nr to after + the model specific fields so the line numbers for the annex are + correct. + * cpu.c (cpu_{create,init,halt}): Check for WITH_MODEL_ISSUE before calling the model functions. @@ -8,15 +18,21 @@ Fri Nov 17 14:08:08 1995 Michael Meissner * igen.c (gen_icache_h): Create type idecode_cache as void if not caching instructions. - (lf_print_c_semantic): Pass idecode_cache and instruction word to - model_issue. - (gen_model_{c,h}): Model_issue now takes two more arguments. - + (gen_model_{c,h}): Drop model_issue support. Add support for + model_cleanup. + (lf_print_my_prefix): Initialize a const itable_index with the + current index. + (lf_print_c_semantic): Call model_cleanup at the end of the + function to check for instructions that aren't supported yet by + the scheduling code. + * mon.h (count_type): New type for counters. * mon.c: Use count_type instead of unsigned. - * ppc-instructions: Reorganize so insn dependent routine is called - via a function pointer. Add initial scheduling code. + * ppc-instructions: Redo scheduling code once again. Make it all + inline friendly. Instead of having general code emitted by igen, + go the route of having each semantic routine call the appropriate + module. Thu Nov 16 09:52:26 1995 Michael Meissner diff --git a/sim/ppc/ppc-instructions b/sim/ppc/ppc-instructions index 8fe8a287481..e0f0a1d7498 100644 --- a/sim/ppc/ppc-instructions +++ b/sim/ppc/ppc-instructions @@ -89,7 +89,7 @@ /* Structure to hold timing information on a per instruction basis */ struct _model_time { ppc_function_unit first_unit; /* first functional unit this insn could use */ - ppc_function_unit last_unit; /* last functional unit this insn could use */ + ppc_function_unit second_unit; /* second functional unit this insn could use */ signed16 issue; /* # cycles before function unit can process other insns */ signed16 done; /* # cycles before insn is done */ unsigned32 flags; /* any flags that are needed */ @@ -128,7 +128,6 @@ model_busy *busy_list; /* list of busy function units */ model_busy *free_list; /* list of model_busy structs not in use */ model_reg registers[NR_PPC_REGS]; /* register status */ - unsigned32 busy_mask; /* bitmask of busy function units */ count_type nr_cycles; /* # cycles */ count_type nr_branches; /* # branches */ count_type nr_branches_fallthrough; /* # conditional branches that fell through */ @@ -140,6 +139,7 @@ count_type nr_insns_not_handled; /* # of instructions not handled */ count_type nr_units[nr_ppc_function_units]; /* function unit counts */ int insn_handled; /* whether last insn was handled */ + unsigned_1 busy[nr_ppc_function_units]; /* whether a function is busy or not */ }; STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = { @@ -168,7 +168,6 @@ void::model-internal::model_new_cycle:model_data *model_ptr model_busy *cur_busy = model_ptr->busy_list; model_busy *free_list = model_ptr->free_list; model_busy *next_busy = (model_busy *)0; - unsigned32 busy_mask = model_ptr->busy_mask; model_busy *next; model_ptr->nr_cycles++; @@ -182,13 +181,13 @@ void::model-internal::model_new_cycle:model_data *model_ptr reg->in_use = 0; reg = reg->next; } - busy_mask &= ~(1 << cur_busy->unit); + model_ptr->busy[cur_busy->unit] = 0; cur_busy->next = free_list; free_list = cur_busy; } else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */ TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit])); - busy_mask &= ~(1 << cur_busy->unit); + model_ptr->busy[cur_busy->unit] = 0; cur_busy->next = next_busy; next_busy = cur_busy; } @@ -204,7 +203,6 @@ void::model-internal::model_new_cycle:model_data *model_ptr model_ptr->busy_list = next_busy; model_ptr->free_list = free_list; - model_ptr->busy_mask = busy_mask; # Mark a function unit as busy, return the busy structure so regs can be added to be released model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done @@ -226,27 +224,27 @@ model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_functio busy->issue = issue; busy->done = done; model_ptr->busy_list = busy; - model_ptr->busy_mask |= (1 << unit); + model_ptr->busy[unit] = 1; model_ptr->nr_units[unit]++; return busy; # Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr ppc_function_unit first_unit = time_ptr->first_unit; - ppc_function_unit last_unit = time_ptr->last_unit; - ppc_function_unit unit; + ppc_function_unit second_unit = time_ptr->second_unit; int stall_increment = 0; for (;;) { - unsigned32 busy_mask = model_ptr->busy_mask; - for (unit = first_unit; unit <= last_unit; unit++) { - if (((1 << unit) & busy_mask) == 0) { - return model_make_busy(model_ptr, unit, - model_ptr->timing[index].issue, - model_ptr->timing[index].done); + if (!model_ptr->busy[first_unit]) + return model_make_busy(model_ptr, first_unit, + model_ptr->timing[index].issue, + model_ptr->timing[index].done); + + if (!model_ptr->busy[second_unit]) + return model_make_busy(model_ptr, second_unit, + model_ptr->timing[index].issue, + model_ptr->timing[index].done); - } - } TRACE(trace_model,("all function units are busy for %s\n", itable[index].name)); model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */ stall_increment = 1; @@ -646,6 +644,62 @@ void::model-function::ppc_insn_mtcr:itable_index index, cpu *processor, model_da busy_ptr->reg = prev_reg; } +# Convert a BIT32(x) number back into the original number +int::model-internal::ppc_undo_bit32:unsigned bitmask + unsigned u = 0x80000000; + int i = 0; + while (u && (u & bitmask) == 0) { + u >>= 1; + i++; + } + + return i; + +# Schedule an instruction that takes 2 CR input registers and produces an output CR register +void::model-function::ppc_insn_cr2:itable_index index, cpu *processor, model_data *model_ptr, unsigned crD, unsigned crA_bit, unsigned crB_bit + if (!WITH_MODEL_ISSUE) + return; + + else { + const unsigned ppc_CRA = ppc_undo_bit32(crA_bit) + PPC_CR_REG; + const unsigned ppc_CRB = ppc_undo_bit32(crB_bit) + PPC_CR_REG; + const unsigned ppc_CRD = crD + PPC_CR_REG; + model_reg *ppc_regs = model_ptr->registers; + model_busy *busy_ptr; + + while (ppc_regs[ppc_CRA].in_use | ppc_regs[ppc_CRB].in_use) { + model_ptr->nr_stalls_data++; + model_new_cycle(model_ptr); + } + + busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); + ppc_regs[ppc_CRD].next = (model_reg *)0; + ppc_regs[ppc_CRD].in_use = 1; + busy_ptr->reg = &ppc_regs[ppc_CRD]; + } + +# Schedule an instruction that takes 1 CR input registers and produces an output CR register +void::model-function::ppc_insn_cr1:itable_index index, cpu *processor, model_data *model_ptr, unsigned crD, unsigned CRA + if (!WITH_MODEL_ISSUE) + return; + + else { + const unsigned ppc_CRA = CRA + PPC_CR_REG; + const unsigned ppc_CRD = crD + PPC_CR_REG; + model_reg *ppc_regs = model_ptr->registers; + model_busy *busy_ptr; + + while (ppc_regs[ppc_CRA].in_use) { + model_ptr->nr_stalls_data++; + model_new_cycle(model_ptr); + } + + busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); + ppc_regs[ppc_CRD].next = (model_reg *)0; + ppc_regs[ppc_CRD].in_use = 1; + busy_ptr->reg = &ppc_regs[ppc_CRD]; + } + model_data *::model-function::model_create:cpu *processor model_data *model_ptr = ZALLOC(model_data); ASSERT(CURRENT_MODEL > 0 && CURRENT_MODEL < nr_models); @@ -1361,6 +1415,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} && CR{BB}); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -1368,6 +1423,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} || CR{BB}); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -1375,6 +1431,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} != CR{BB}); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -1382,6 +1439,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, !(CR{BA} && CR{BB})); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -1389,6 +1447,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, !(CR{BA} || CR{BB})); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -1396,6 +1455,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} == CR{BB}); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -1403,6 +1463,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} && !CR{BB}); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0 @@ -1410,6 +1471,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 BLIT32(CR, BT, CR{BA} || !CR{BB}); + ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB); # # I.2.4.4 Condition Register Field Instruction @@ -1420,6 +1482,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3)); + ppc_insn_cr1(my_index, processor, cpu_model(processor), BF, BFA); # -- 2.30.2