src/packet_build.c
Flag packet_build(Pb_Data* pb_data, Break_Reason* break_fetch, Op* const op,
                  uns const index) {
  Break_Reason model_break_result;

  ASSERT(pb_data->proc_id, pb_data->proc_id == op->proc_id);

  if(pb_data->pb_ident == PB_ICACHE) {
    // only have constraints on the number of loads & stores per packet
    if(NUM_LOAD_STORE_PER_PACKET) {
      pb_data->break_conditions[NUM_LOAD_STORE] += (op->table_info->mem_type !=
                                                    0);
      if(pb_data->break_conditions[NUM_LOAD_STORE] >
         NUM_LOAD_STORE_PER_PACKET) {
        *break_fetch = 100;
        return PB_BREAK_BEFORE;
      }
    }

    // break when no more functional units are available
    if(PACKET_BREAK_ON_FUS) {
      int ii;
      // search for avail fus starting with the most specific FU type
      for(ii = 0; ii < PB_NUM_FU_TYPES; ii++) {
        if((1 << op->table_info->op_type) & pb_data->fu_info[ii].type) {
          if(pb_data->fu_info[ii].count < pb_data->fu_info[ii].max) {
            pb_data->fu_info[ii].count++;
            break;
          } else {
            *break_fetch = 100;
            /* used for tcache */
            return PB_BREAK_BEFORE;
          }
        }
      }
    }

    // this must be called as the last BREAK_BEFORE condition
    model_break_result = model->break_hook ? model->break_hook(op) : BREAK_DONT;
    if(model_break_result) {
      *break_fetch = BREAK_MODEL_BEFORE;
      return PB_BREAK_BEFORE;
    }

    // hit fetch barrier
    if(IS_CALLSYS(op->table_info) || op->table_info->bar_type & BAR_FETCH) {
      *break_fetch = BREAK_BARRIER;
      return PB_BREAK_AFTER;
    }

    if(ENABLE_ICACHE_PACKET_BREAKING) {
      // reached a max number of control flow instructions
      pb_data->break_conditions[NUM_CF] += (op->table_info->cf_type != 0);
      if(pb_data->break_conditions[NUM_CF] == CFS_PER_CYCLE) {
        *break_fetch = BREAK_CF;
        return PB_BREAK_AFTER;
      }

      // fetch across cache lines
      if(pb_data->pb_ident == PB_ICACHE) {
        int offset = op->inst_info->addr -
                     ROUND_DOWN(op->inst_info->addr, ICACHE_LINE_SIZE);
        if(offset >= ICACHE_LINE_SIZE && !FETCH_ACROSS_CACHE_LINES) {
          *break_fetch = BREAK_LINE_END;
          // Inaccuracy: this allows the last instruction in the
          // cache line to be issued even if it spills into the
          // next cache line.
          return PB_BREAK_AFTER;
        }
      }
    }

    // issue width reached
    if(pb_data->pb_ident == PB_ICACHE) {
      if(ic->sd.op_count + 1 == ISSUE_WIDTH) {
        *break_fetch = BREAK_ISSUE_WIDTH;
        return PB_BREAK_AFTER;
      }
    }

    if(ENABLE_ICACHE_PACKET_BREAKING) {
      // control flow instruction
      if(op->table_info->cf_type)
        return PB_BREAK_AFTER;
    }
  }

  return PB_BREAK_DONT;
}
/**************************************************************************************/
/* Packet_build:
   return 0 if packet should break after current op
   return 1 if otherwise
*/
return 0 if packet should break after current op
return 1 if otherwise
return 0 if packet should break after current op return 1 if otherwise
Flag packet_build(Pb_Data* pb_data, Break_Reason* break_fetch, Op* const op,
                  uns const index) {
  Break_Reason model_break_result;
  ASSERT(pb_data->proc_id, pb_data->proc_id == op->proc_id);
  if(pb_data->pb_ident == PB_ICACHE) {
    if(NUM_LOAD_STORE_PER_PACKET) {
      pb_data->break_conditions[NUM_LOAD_STORE] += (op->table_info->mem_type !=
                                                    0);
      if(pb_data->break_conditions[NUM_LOAD_STORE] >
         NUM_LOAD_STORE_PER_PACKET) {
        *break_fetch = 100;
        return PB_BREAK_BEFORE;
      }
    }
    if(PACKET_BREAK_ON_FUS) {
      int ii;
      for(ii = 0; ii < PB_NUM_FU_TYPES; ii++) {
        if((1 << op->table_info->op_type) & pb_data->fu_info[ii].type) {
          if(pb_data->fu_info[ii].count < pb_data->fu_info[ii].max) {
            pb_data->fu_info[ii].count++;
            break;
          } else {
            *break_fetch = 100;
            return PB_BREAK_BEFORE;
          }
        }
      }
    }
    model_break_result = model->break_hook ? model->break_hook(op) : BREAK_DONT;
    if(model_break_result) {
      *break_fetch = BREAK_MODEL_BEFORE;
      return PB_BREAK_BEFORE;
    }
    if(IS_CALLSYS(op->table_info) || op->table_info->bar_type & BAR_FETCH) {
      *break_fetch = BREAK_BARRIER;
      return PB_BREAK_AFTER;
    }
    if(ENABLE_ICACHE_PACKET_BREAKING) {
      pb_data->break_conditions[NUM_CF] += (op->table_info->cf_type != 0);
      if(pb_data->break_conditions[NUM_CF] == CFS_PER_CYCLE) {
        *break_fetch = BREAK_CF;
        return PB_BREAK_AFTER;
      }
      if(pb_data->pb_ident == PB_ICACHE) {
        int offset = op->inst_info->addr -
                     ROUND_DOWN(op->inst_info->addr, ICACHE_LINE_SIZE);
        if(offset >= ICACHE_LINE_SIZE && !FETCH_ACROSS_CACHE_LINES) {
          *break_fetch = BREAK_LINE_END;
          return PB_BREAK_AFTER;
        }
      }
    }
    if(pb_data->pb_ident == PB_ICACHE) {
      if(ic->sd.op_count + 1 == ISSUE_WIDTH) {
        *break_fetch = BREAK_ISSUE_WIDTH;
        return PB_BREAK_AFTER;
      }
    }
    if(ENABLE_ICACHE_PACKET_BREAKING) {
      if(op->table_info->cf_type)
        return PB_BREAK_AFTER;
    }
  }
  return PB_BREAK_DONT;
}
Flag packet_build ( Pb_Data * pb_data , Break_Reason * break_fetch , Op * const op , uns const index ) { Break_Reason model_break_result ; ASSERT ( pb_data -> proc_id , pb_data -> proc_id == op -> proc_id ) ; if ( pb_data -> pb_ident == PB_ICACHE ) { if ( NUM_LOAD_STORE_PER_PACKET ) { pb_data -> break_conditions [ NUM_LOAD_STORE ] += ( op -> table_info -> mem_type != 0 ) ; if ( pb_data -> break_conditions [ NUM_LOAD_STORE ] > NUM_LOAD_STORE_PER_PACKET ) { * break_fetch = 100 ; return PB_BREAK_BEFORE ; } } if ( PACKET_BREAK_ON_FUS ) { int ii ; for ( ii = 0 ; ii < PB_NUM_FU_TYPES ; ii ++ ) { if ( ( 1 << op -> table_info -> op_type ) & pb_data -> fu_info [ ii ] . type ) { if ( pb_data -> fu_info [ ii ] . count < pb_data -> fu_info [ ii ] . max ) { pb_data -> fu_info [ ii ] . count ++ ; break ; } else { * break_fetch = 100 ; return PB_BREAK_BEFORE ; } } } } model_break_result = model -> break_hook ? model -> break_hook ( op ) : BREAK_DONT ; if ( model_break_result ) { * break_fetch = BREAK_MODEL_BEFORE ; return PB_BREAK_BEFORE ; } if ( IS_CALLSYS ( op -> table_info ) || op -> table_info -> bar_type & BAR_FETCH ) { * break_fetch = BREAK_BARRIER ; return PB_BREAK_AFTER ; } if ( ENABLE_ICACHE_PACKET_BREAKING ) { pb_data -> break_conditions [ NUM_CF ] += ( op -> table_info -> cf_type != 0 ) ; if ( pb_data -> break_conditions [ NUM_CF ] == CFS_PER_CYCLE ) { * break_fetch = BREAK_CF ; return PB_BREAK_AFTER ; } if ( pb_data -> pb_ident == PB_ICACHE ) { int offset = op -> inst_info -> addr - ROUND_DOWN ( op -> inst_info -> addr , ICACHE_LINE_SIZE ) ; if ( offset >= ICACHE_LINE_SIZE && ! FETCH_ACROSS_CACHE_LINES ) { * break_fetch = BREAK_LINE_END ; return PB_BREAK_AFTER ; } } } if ( pb_data -> pb_ident == PB_ICACHE ) { if ( ic -> sd . op_count + 1 == ISSUE_WIDTH ) { * break_fetch = BREAK_ISSUE_WIDTH ; return PB_BREAK_AFTER ; } } if ( ENABLE_ICACHE_PACKET_BREAKING ) { if ( op -> table_info -> cf_type ) return PB_BREAK_AFTER ; } } return PB_BREAK_DONT ; }
Packet_build:
return 0 if packet should break after current op
return 1 if otherwise
Packet_build : return 0 if packet should break after current op return 1 if otherwise
// only have constraints on the number of loads & stores per packet // break when no more functional units are available // search for avail fus starting with the most specific FU type /* used for tcache */ // this must be called as the last BREAK_BEFORE condition // hit fetch barrier // reached a max number of control flow instructions // fetch across cache lines // Inaccuracy: this allows the last instruction in the // cache line to be issued even if it spills into the // next cache line. // issue width reached // control flow instruction