summaryrefslogtreecommitdiff
path: root/lib/cycles_to_energy.py
blob: ec449ca6dfeb7b2d4bc23b151ef4598e7d846dd5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""
Convert CPU cycle count to energy.

Contains classes for some embedded CPUs/MCUs. Given a configuration, each
class can convert a cycle count to an energy consumption.
"""

def get_class(cpu_name):
    """Return model class for cpu_name."""
    if cpu_name == 'MSP430':
        return MSP430
    if cpu_name == 'ATMega168':
        return ATMega168
    if cpu_name == 'ATMega328':
        return ATMega328
    if cpu_name == 'ATTiny88':
        return ATTiny88

def _param_list_to_dict(device, param_list):
    param_dict = dict()
    for i, parameter in enumerate(sorted(device.parameters.keys())):
        param_dict[parameter] = param_list[i]
    return param_dict

class MSP430:
    name = 'MSP430'
    parameters = {
        'cpu_freq': [1e6, 4e6, 8e6, 12e6, 16e6],
        'memory' : ['unified', 'fram0', 'fram50', 'fram66', 'fram75', 'fram100', 'ram'],
        'voltage': [2.2, 3.0],
    }
    default_params = {
        'cpu_freq': 4e6,
        'memory' : 'unified',
        'voltage': 3
    }

    current_by_mem = {
        'unified' : [210,  640, 1220, 1475, 1845],
        'fram0'   : [370, 1280, 2510, 2080, 2650],
        'fram50'  : [240,  745, 1440, 1575, 1990],
        'fram66'  : [200,  560, 1070, 1300, 1620],
        'fram75'  : [170,  480,  890, 1155, 1420],
        'fram100' : [110,  235,  420,  640,  730],
        'ram'     : [130,  320,  585,  890, 1070],
    }

    def get_current(params):
        if type(params) != dict:
            return MSP430.get_current(_param_list_to_dict(MSP430, params))
        cpu_freq_index = MSP430.parameters['cpu_freq'].index(params['cpu_freq'])

        return MSP430.current_by_mem[params['memory']][cpu_freq_index] * 1e-6

    def get_power(params):
        if type(params) != dict:
            return MSP430.get_energy(_param_list_to_dict(MSP430, params))

        return MSP430.get_current(params) * params['voltage']

    def get_energy_per_cycle(params):
        if type(params) != dict:
            return MSP430.get_energy(_param_list_to_dict(MSP430, params))

        return MSP430.get_power(params) / params['cpu_freq']

class ATMega168:
    name = 'ATMega168'
    parameters = {
        'cpu_freq': [1e6, 4e6, 8e6],
        'voltage': [2, 3, 5]
    }
    default_params = {
        'cpu_freq': 4e6,
        'voltage': 3
    }

    def get_current(params):
        if type(params) != dict:
            return ATMega168.get_current(_param_list_to_dict(ATMega168, params))
        if params['cpu_freq'] == 1e6 and params['voltage'] <= 2:
            return 0.5e-3
        if params['cpu_freq'] == 4e6 and params['voltage'] <= 3:
            return 3.5e-3
        if params['cpu_freq'] == 8e6 and params['voltage'] <= 5:
            return 12e-3
        return None

    def get_power(params):
        if type(params) != dict:
            return ATMega168.get_energy(_param_list_to_dict(ATMega168, params))

        return ATMega168.get_current(params) * params['voltage']

    def get_energy_per_cycle(params):
        if type(params) != dict:
            return ATMega168.get_energy(_param_list_to_dict(ATMega168, params))

        return ATMega168.get_power(params) / params['cpu_freq']

class ATMega328:
    name = 'ATMega328'
    parameters = {
        'cpu_freq': [1e6, 4e6, 8e6],
        'voltage': [2, 3, 5]
    }
    default_params = {
        'cpu_freq': 4e6,
        'voltage': 3
    }

    def get_current(params):
        if type(params) != dict:
            return ATMega328.get_current(_param_list_to_dict(ATMega328, params))
        if params['cpu_freq'] == 1e6 and params['voltage'] <= 2:
            return 0.5e-3
        if params['cpu_freq'] == 4e6 and params['voltage'] <= 3:
            return 3.5e-3
        if params['cpu_freq'] == 8e6 and params['voltage'] <= 5:
            return 12e-3
        return None

    def get_power(params):
        if type(params) != dict:
            return ATMega328.get_energy(_param_list_to_dict(ATMega328, params))

        return ATMega328.get_current(params) * params['voltage']

    def get_energy_per_cycle(params):
        if type(params) != dict:
            return ATMega328.get_energy(_param_list_to_dict(ATMega328, params))

        return ATMega328.get_power(params) / params['cpu_freq']

class ATTiny88:
    name = 'ATTiny88'
    parameters = {
        'cpu_freq': [1e6, 4e6, 8e6],
        'voltage': [2, 3, 5]
    }
    default_params = {
        'cpu_freq' : 4e6,
        'voltage' : 3
    }

    def get_current(params):
        if type(params) != dict:
            return ATTiny88.get_current(_param_list_to_dict(ATTiny88, params))
        if params['cpu_freq'] == 1e6 and params['voltage'] <= 2:
            return 0.2e-3
        if params['cpu_freq'] == 4e6 and params['voltage'] <= 3:
            return 1.4e-3
        if params['cpu_freq'] == 8e6 and params['voltage'] <= 5:
            return 4.5e-3
        return None