Beispiel #1
0
def compute_area():  #in mm2
    area = 0.0
    #area += cfg.num_tile_compute * tile_metrics.compute_area ()
    #area += param.noc_intra_area * (cfg.num_node*(cfg.num_tile_compute+2)) / float(cfg.cmesh_c)
    # Area of all tiles on chip
    area += cfg.num_tile_max * tile_metrics.compute_area()
    area += param.noc_intra_area * (cfg.num_node *
                                    (cfg.num_tile_max)) / float(cfg.cmesh_c)
    area += param.noc_inter_area
    #print ('Node area excludes NOC: ', area)
    return area
Beispiel #2
0
def get_hw_stats (fid, node_dut, cycle):

    # List of all components that dissipate power
    hw_comp_access = {'xbar':0, 'dac':0, 'snh':0, \
            'mux1':0, 'mux2':0, 'adc':0, \
            'alu_div':0, 'alu_mul':0, \
            'alu_act':0, 'alu_other':0, \
            'alu_sna':0, \
            'imem':0, 'dmem':0, 'xbInmem_rd':0, \
            'xbInmem_wr':0, 'xbOutmem':0, \
            'imem_t':0, 'rbuff':0, \
            'edram':0, 'edctrl':0, \
            'edram_bus':0, 'edctrl_counter':0, \
            'noc_intra':0, 'noc_inter':0, \
            'core_control':0, 'tile_control': 0 \
            }

    # traverse components to populate dict (hw_comp_access)
    hw_comp_access['noc_intra'] += node_dut.noc.num_cycles_intra
    # From tile0 instructions find the repetitions and scale down
    # HACK - modify this based on data sharing across output tiles [IZZAT] terminology] in a node
    hw_comp_access['noc_inter'] += node_dut.noc.num_access_inter/12

    # Count num_cycles for leakage energy computations (power-gating granularity: ima/tile/noc)
    sum_num_cycle_tile = 0
    sum_num_cycle_ima = 0
    sum_num_cycle_noc = node_dut.noc.num_cycles_intra


    for i in range (2, cfg.num_tile): # ignore dummy (input & output) tiles
        sum_num_cycle_tile += node_dut.tile_list[i].cycle_count # used for leakage energy of tiles

        hw_comp_access['imem_t'] += node_dut.tile_list[i].instrn_memory.num_access
        hw_comp_access['rbuff'] += node_dut.tile_list[i].receive_buffer.num_access
        hw_comp_access['edram'] += node_dut.tile_list[i].edram_controller.mem.num_access
        hw_comp_access['edram_bus'] += node_dut.tile_list[i].edram_controller.mem.num_access
        hw_comp_access['edctrl'] += node_dut.tile_list[i].edram_controller.num_access
        hw_comp_access['edctrl_counter'] += node_dut.tile_list[i].edram_controller.num_access_counter

        for j in range (cfg.num_ima):
            sum_num_cycle_ima += node_dut.tile_list[i].ima_list[j].cycle_count # used for leakage energy of imas

            for k in range (cfg.num_xbar):
                hw_comp_access['xbar'] += node_dut.tile_list[i].ima_list[j].xbar_list[k].num_access

            for k in range (cfg.num_xbar/(cfg.data_width/cfg.xbar_bits)):
                for l in range (cfg.xbar_size):
                    hw_comp_access['dac'] += node_dut.tile_list[i].ima_list[j].dacArray_list[k].dac_list[l].num_access

            for k in range (cfg.num_xbar):
                hw_comp_access['snh'] += (node_dut.tile_list[i].ima_list[j].snh_list[k].num_access * cfg.xbar_size) # each snh is
                # basically an array of multiple snhs (individual power in constants file must be for one discerete snh)

            for k in range (cfg.num_xbar):
                hw_comp_access['mux1'] += node_dut.tile_list[i].ima_list[j].mux1_list[k].num_access

            for k in range (cfg.num_xbar / cfg.num_adc):
                hw_comp_access['mux2'] += node_dut.tile_list[i].ima_list[j].mux1_list[k].num_access

            for k in range (cfg.num_adc):
                hw_comp_access['adc'] += node_dut.tile_list[i].ima_list[j].adc_list[k].num_access

            for k in range (cfg.num_ALU):
                hw_comp_access['alu_div'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_div + \
                        node_dut.tile_list[i].ima_list[j].alu_int.num_access_div

                hw_comp_access['alu_mul'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_mul + \
                        node_dut.tile_list[i].ima_list[j].alu_int.num_access_mul

                hw_comp_access['alu_other'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_other + \
                        node_dut.tile_list[i].ima_list[j].alu_int.num_access_other

                hw_comp_access['alu_act'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_act

                hw_comp_access['alu_sna'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_sna

            hw_comp_access['imem'] += node_dut.tile_list[i].ima_list[j].instrnMem.num_access

            hw_comp_access['dmem'] += node_dut.tile_list[i].ima_list[j].dataMem.num_access

            for k in range (cfg.num_xbar/(cfg.data_width/cfg.xbar_bits)):
                hw_comp_access['xbInmem_rd'] += node_dut.tile_list[i].ima_list[j].xb_inMem_list[k].num_access_read
                hw_comp_access['xbInmem_wr'] += node_dut.tile_list[i].ima_list[j].xb_inMem_list[k].num_access_write

            for k in range (cfg.num_xbar/(cfg.data_width/cfg.xbar_bits)):
                hw_comp_access['xbOutmem'] += node_dut.tile_list[i].ima_list[j].xb_outMem_list[k].num_access


    # Added for core and tile control units
    hw_comp_access['core_control'] = sum_num_cycle_tile
    hw_comp_access['tile_control'] = sum_num_cycle_ima

    total_energy = 0
    # Compute the total dynamic energy consumption
    for key, value in hw_comp_access.items():
        total_energy += value * hw_comp_energy[key]

    # Write the dict comp_access & energy proportion to a file for visualization
    fid.write ('Access and energy distribution of dynamic energy: \n')
    fid.write ('Component                 num_access              percent\n')
    for key, value in hw_comp_access.items():
        # put extra spaces for better visulalization of values
        bl_spc1 = (28-len(key)) * ' '
        bl_spc2 = (22-len(str(value))) * ' '
        fid.write (key + bl_spc1 + str(value) + bl_spc2 +\
                    (str(value*hw_comp_energy[key]/total_energy*100))[0:4] + ' %\n')

    fid.write ('\n')


    # Evaluate leakage_energy (tile/ima/noc is power-gated if unused
    leakage_energy = sum_num_cycle_noc * param.noc_intra_pow_leak + \
            sum_num_cycle_tile * tile_metrics.compute_pow_leak_non_ima () + \
            sum_num_cycle_ima * ima_metrics.compute_pow_leak()


    # Write the leakage energy(J), total_energy(J), average_power (mW), peak_power (mW),
    # area (mm2), cycles and time (seconds) to a dict & file
    metric_dict = {'leakage_energy':0.0,
            'dynamic_energy':0.0,
            'total_energy':0.0,
            'average_power':0.0,
            'peak_power':0.0,
            'leakage_power':0.0,
            'node_area':0.0,
            'tile_area':0.0,
            'core_area':0.0,
            'cycles':0,
            'time':0.0}

    metric_dict['leakage_power'] = node_metrics.compute_pow_leak () # in mW
    metric_dict['peak_power'] = node_metrics.compute_pow_peak () # in mW
    metric_dict['node_area'] = node_metrics.compute_area () # in mm2
    metric_dict['tile_area'] = tile_metrics.compute_area ()# in mm2
    metric_dict['core_area'] = ima_metrics.compute_area ()# in mm2
    metric_dict['cycles'] = cycle
    metric_dict['time'] = cycle * param.cycle_time * (10**(-9)) # in sec
    metric_dict['dynamic_energy'] = total_energy * ns * mw # in joule
    #metric_dict['leakage_enegy'] = metric_dict['leakage_power'] * mw * metric_dict['time'] # in joule
    metric_dict['leakage_energy'] =  leakage_energy * ns * mw # in joule
    metric_dict['total_energy'] = metric_dict['dynamic_energy'] + metric_dict['leakage_energy']
    metric_dict['average_power'] = metric_dict['total_energy'] / metric_dict['time'] * (10**(3)) # in mW

    for key, value in metric_dict.items():
        fid.write (key + ': ' + str (value) + '\n')

    packet_inj_rate = node_dut.noc.num_access_intra/ (metric_dict['cycles'] * cfg.num_inj_max)
    fid.write ('network packet injection rate: ' + str(packet_inj_rate) + '\n')
    fid.write ('number of tiles mapped: ' + str(cfg.num_tile_compute))

    return metric_dict
Beispiel #3
0
def get_hw_stats(fid, node_dut, cycle):

    # List of all components that dissipate power
    hw_comp_access = {'xbar_mvm':{  '0':0, '90': 0,'80': 0,'70': 0,'60': 0,'50': 0,'40': 0,'30': 0,'20': 0,'10': 0}, \
            'xbar_op':0, 'xbar_mtvm':0, \
            'xbar_rd':0, 'xbar_wr':0, \
            'dac':0, 'snh':0, \
            'mux1':0, 'mux2':0, 'adc':{ 'n' :    0, \
                                        'n/2':   0, \
                                        'n/4':   0, \
                                        'n/8':   0, \
                                        'n/16':  0, \
                                        'n/32':  0, \
                                        'n/64':  0, \
                                        'n/128': 0}, \
            'alu_div':0, 'alu_mul':0, \
            'alu_act':0, 'alu_other':0, \
            'alu_sna':0, \
            'imem':0, 'dmem':0, 'xbInmem_rd':0, \
            'xbInmem_wr':0, 'xbOutmem':0, \
            'imem_t':0, 'rbuff':0, \
            'edram':0, 'edctrl':0, \
            'edram_bus':0, 'edctrl_counter':0, \
            'noc_intra':0, 'noc_inter':0, \
            'core_control':0, 'tile_control': 0 \
            }

    # traverse components to populate dict (hw_comp_access)
    hw_comp_access['noc_intra'] += node_dut.noc.num_cycles_intra
    # From tile0 instructions find the repetitions and scale down
    # HACK - modify this based on data sharing across output tiles [IZZAT] terminology] in a node
    hw_comp_access['noc_inter'] += node_dut.noc.num_access_inter / 12

    # Count num_cycles for leakage energy computations (power-gating granularity: ima/tile/noc)
    sum_num_cycle_tile = 0
    sum_num_cycle_ima = 0
    sum_num_cycle_noc = node_dut.noc.num_cycles_intra

    for i in range(1, cfg.num_tile):  # ignore dummy (input & output) tiles
        sum_num_cycle_tile += node_dut.tile_list[
            i].cycle_count  # used for leakage energy of tiles

        hw_comp_access['imem_t'] += node_dut.tile_list[
            i].instrn_memory.num_access
        hw_comp_access['rbuff'] += node_dut.tile_list[
            i].receive_buffer.num_access
        hw_comp_access['edram'] += node_dut.tile_list[
            i].edram_controller.mem.num_access
        hw_comp_access['edram_bus'] += node_dut.tile_list[
            i].edram_controller.mem.num_access
        hw_comp_access['edctrl'] += node_dut.tile_list[
            i].edram_controller.num_access
        hw_comp_access['edctrl_counter'] += node_dut.tile_list[
            i].edram_controller.num_access_counter

        for j in range(cfg.num_ima):
            sum_num_cycle_ima += node_dut.tile_list[i].ima_list[
                j].cycle_count  # used for leakage energy of imas
            mvmu_type = ['f', 'b', 'd']
            for k in range(cfg.num_matrix):
                for mvmu_t in mvmu_type:
                    # Xbar accesses
                    if cfg.MVMU_ver == "Analog":
                        for m in range(cfg.phy2log_ratio):
                            if (mvmu_t == 'd'):
                                hw_comp_access[
                                    'xbar_op'] += node_dut.tile_list[
                                        i].ima_list[j].matrix_list[k][mvmu_t][
                                            m].num_access['0']
                            elif (mvmu_t == 'b'):
                                hw_comp_access[
                                    'xbar_mtvm'] += node_dut.tile_list[
                                        i].ima_list[j].matrix_list[k][mvmu_t][
                                            m].num_access['0']
                            else:
                                for key, value in hw_comp_access[
                                        'xbar_mvm'].items():
                                    hw_comp_access['xbar_mvm'][
                                        key] += node_dut.tile_list[i].ima_list[
                                            j].matrix_list[k][mvmu_t][
                                                m].num_access[key]
                            hw_comp_access['xbar_rd'] += \
                            node_dut.tile_list[i].ima_list[j].matrix_list[k][mvmu_t][m].num_access_rd / (cfg.xbar_size**2)
                            hw_comp_access['xbar_wr'] += \
                            node_dut.tile_list[i].ima_list[j].matrix_list[k][mvmu_t][m].num_access_wr / (cfg.xbar_size**2)

                    else:
                        if (mvmu_t == 'd'):
                            hw_comp_access['xbar_op'] += node_dut.tile_list[
                                i].ima_list[j].matrix_list[k][mvmu_t][
                                    0].num_access['0']
                        elif (mvmu_t == 'b'):
                            hw_comp_access['xbar_mtvm'] += node_dut.tile_list[
                                i].ima_list[j].matrix_list[k][mvmu_t][
                                    0].num_access['0']
                        else:
                            for key, value in hw_comp_access['xbar_mvm'].items(
                            ):
                                hw_comp_access['xbar_mvm'][
                                    key] += node_dut.tile_list[i].ima_list[
                                        j].matrix_list[k][mvmu_t][
                                            0].num_access[key]
                        hw_comp_access['xbar_rd'] += \
                        node_dut.tile_list[i].ima_list[j].matrix_list[k][mvmu_t][0].num_access_rd / (cfg.xbar_size**2)
                        hw_comp_access['xbar_wr'] += \
                        node_dut.tile_list[i].ima_list[j].matrix_list[k][mvmu_t][0].num_access_wr / (cfg.xbar_size**2)

                    # Xb_InMem accesses
                    if cfg.MVMU_ver == "Analog":
                        hw_comp_access['xbInmem_rd'] += node_dut.tile_list[
                            i].ima_list[j].xb_inMem_list[k][
                                mvmu_t].num_access_read
                    hw_comp_access['xbInmem_wr'] += node_dut.tile_list[
                        i].ima_list[j].xb_inMem_list[k][
                            mvmu_t].num_access_write
                    # Xb_OutMem accesses
                    if cfg.MVMU_ver == "Analog":
                        hw_comp_access['xbOutmem'] += node_dut.tile_list[
                            i].ima_list[j].xb_outMem_list[k][mvmu_t].num_access

            for k in range(cfg.num_matrix):
                dac_type = ['f', 'b', 'd_r', 'd_c']
                for dac_t in dac_type:
                    for l in range(cfg.xbar_size):
                        if cfg.MVMU_ver == "Analog":
                            hw_comp_access['dac'] += node_dut.tile_list[
                                i].ima_list[j].dacArray_list[k][
                                    dac_t].dac_list[l].num_access

            if cfg.MVMU_ver == "Analog":
                for k in range(2 * cfg.num_matrix * cfg.phy2log_ratio):
                    hw_comp_access['snh'] += (
                        node_dut.tile_list[i].ima_list[j].snh_list[k].
                        num_access * cfg.xbar_size)  # each snh is
                    # basically an array of multiple snhs (individual power in constants file must be for one discerete snh)

            for k in range(2 * cfg.num_matrix):
                hw_comp_access['mux1'] += node_dut.tile_list[i].ima_list[
                    j].mux1_list[k].num_access

            for k in range(cfg.num_adc):
                hw_comp_access['mux2'] += node_dut.tile_list[i].ima_list[
                    j].mux1_list[k].num_access

            if cfg.MVMU_ver == "Analog":
                for k in range(cfg.num_adc):
                    for key, value in hw_comp_access['adc'].items():
                        hw_comp_access['adc'][key] += node_dut.tile_list[
                            i].ima_list[j].adc_list[k].num_access[key]

            for k in range(cfg.num_ALU):
                hw_comp_access['alu_div'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_div + \
                        node_dut.tile_list[i].ima_list[j].alu_int.num_access_div

                hw_comp_access['alu_mul'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_mul + \
                        node_dut.tile_list[i].ima_list[j].alu_int.num_access_mul

                hw_comp_access['alu_other'] += node_dut.tile_list[i].ima_list[j].alu_list[k].num_access_other + \
                        node_dut.tile_list[i].ima_list[j].alu_int.num_access_other

                hw_comp_access['alu_act'] += node_dut.tile_list[i].ima_list[
                    j].alu_list[k].num_access_act

                hw_comp_access['alu_sna'] += node_dut.tile_list[i].ima_list[
                    j].alu_list[k].num_access_sna

            hw_comp_access['imem'] += node_dut.tile_list[i].ima_list[
                j].instrnMem.num_access

            hw_comp_access['dmem'] += node_dut.tile_list[i].ima_list[
                j].dataMem.num_access

    # Added for core and tile control units
    hw_comp_access['core_control'] = sum_num_cycle_ima
    hw_comp_access['tile_control'] = sum_num_cycle_tile

    total_energy = 0
    total_adc_energy = 0
    total_adc_access = 0
    total_mvm_energy = 0
    total_mvm_access = 0
    # Compute the total dynamic energy consumption
    if cfg.MVMU_ver == "Analog":
        for key, value in hw_comp_access.items():
            if key == 'adc':
                for key1, value1 in hw_comp_access['adc'].items():
                    total_energy += value1 * hw_comp_energy['adc'][key1]
                    total_adc_energy += value1 * hw_comp_energy['adc'][
                        key1]  # Not needed for function but for output visualisation
                    total_adc_access += value1
            elif key == 'xbar_mvm':
                for key1, value1 in hw_comp_access['xbar_mvm'].items():
                    total_energy += value1 * hw_comp_energy['xbar_mvm'][key1]
                    total_mvm_energy += value1 * hw_comp_energy['xbar_mvm'][
                        key1]  # Not needed for function but for output visualisation
                    total_mvm_access += value1
            else:
                total_energy += value * hw_comp_energy[key]
    else:
        for key, value in hw_comp_access.items():
            if key == 'adc':
                for key1, value1 in hw_comp_access['adc'].items():
                    total_energy += value1 * hw_comp_energy['adc'][key1]
                    total_adc_energy += value1 * hw_comp_energy['adc'][
                        key1]  # Not needed for function but for output visualisation
                    total_adc_access += value1
            elif key == 'xbar_mvm':
                for key1, value1 in hw_comp_access['xbar_mvm'].items():
                    total_energy += (value1 /
                                     16) * hw_comp_energy['xbar_mvm'][key1]
                    total_mvm_energy += (
                        value1 / 16
                    ) * hw_comp_energy['xbar_mvm'][
                        key1]  # Not needed for function but for output visualisation
                    total_mvm_access += (value1 / 16)
            else:
                total_energy += value * hw_comp_energy[key]

    # Write the dict comp_access & energy proportion to a file for visualization
    fid.write("MVMU Type : " + cfg.MVMU_ver + "\n")
    fid.write('Access and energy distribution of dynamic energy: \n')
    fid.write('Component                 num_access              percent\n')
    for key, value in hw_comp_access.items():
        # put extra spaces for better visulalization of values
        bl_spc1 = (28 - len(key)) * ' '
        # bl_spc2 = (22-len(str(value))) * ' '
        if key == 'adc':
            bl_spc2 = (22 - len(str(total_adc_access))) * ' '
            fid.write (key + bl_spc1 + str(total_adc_access) + bl_spc2 +\
                        (str(total_adc_energy/total_energy*100))[0:4] + ' %\n')
        elif key == 'xbar_mvm':
            bl_spc2 = (22 - len(str(total_mvm_access))) * ' '
            fid.write (key + bl_spc1 + str(total_mvm_access) + bl_spc2 +\
                        (str(total_mvm_energy/total_energy*100))[0:4] + ' %\n')
        else:
            bl_spc2 = (22 - len(str(value))) * ' '
            fid.write (key + bl_spc1 + str(value) + bl_spc2 +\
                        (str(value*hw_comp_energy[key]/total_energy*100))[0:4] + ' %\n')

    fid.write('\n')

    # Evaluate leakage_energy (tile/ima/noc is power-gated if unused
    leakage_energy = sum_num_cycle_noc * param.noc_intra_pow_leak + \
            sum_num_cycle_tile * tile_metrics.compute_pow_leak_non_ima () + \
            sum_num_cycle_ima * ima_metrics.compute_pow_leak()

    # Write the leakage energy(J), total_energy(J), average_power (mW), peak_power (mW),
    # area (mm2), cycles and time (seconds) to a dict & file
    metric_dict = {
        'leakage_energy': 0.0,
        'dynamic_energy': 0.0,
        'total_energy': 0.0,
        'average_power': 0.0,
        'peak_power': 0.0,
        'leakage_power': 0.0,
        'node_area': 0.0,
        'tile_area': 0.0,
        'core_area': 0.0,
        'cycles': 0,
        'time': 0.0
    }

    metric_dict['leakage_power'] = node_metrics.compute_pow_leak()  # in mW
    metric_dict['peak_power'] = node_metrics.compute_pow_peak()  # in mW
    metric_dict['node_area'] = node_metrics.compute_area()  # in mm2
    metric_dict['tile_area'] = tile_metrics.compute_area()  # in mm2
    metric_dict['core_area'] = ima_metrics.compute_area()  # in mm2
    metric_dict['cycles'] = cycle
    metric_dict['time'] = cycle * param.cycle_time * (10**(-9))  # in sec
    metric_dict['dynamic_energy'] = total_energy * ns * mw  # in joule
    #metric_dict['leakage_enegy'] = metric_dict['leakage_power'] * mw * metric_dict['time'] # in joule
    metric_dict['leakage_energy'] = leakage_energy * ns * mw  # in joule
    metric_dict['total_energy'] = metric_dict['dynamic_energy'] + metric_dict[
        'leakage_energy']
    metric_dict['average_power'] = metric_dict['total_energy'] / metric_dict[
        'time'] * (10**(3))  # in mW

    for key, value in metric_dict.items():
        fid.write(key + ': ' + str(value) + '\n')

    packet_inj_rate = node_dut.noc.num_access_intra / (metric_dict['cycles'] *
                                                       cfg.num_inj_max)
    fid.write('network packet injection rate: ' + str(packet_inj_rate) + '\n')
    fid.write('number of tiles mapped: ' + str(cfg.num_tile_compute))

    return metric_dict