summaryrefslogtreecommitdiffstats
path: root/woferclock/update_poundv_buckets
blob: a21b3f2e6750cf2e1e405ae7fbbf4be215e04ad5 (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/python
#
# Copyright (c) 2018 Raptor Engineering, LLC
# Released under the terms of the AGPL v3
#
# NOTE:
# #V bucket layout documented in p9_pm_get_poundv_bucket.H,
# type voltageBucketData_t

import sys
import binascii

def show_poundv_bucket_mode_data(mode_data, friendly_name):
    print "\t" + friendly_name + ":"
    print "\t\tFrequency:\t" + mode_data[0] + " (" + str(int(mode_data[0], 16)) + " MHz)"
    print "\t\tVDD Nominal:\t" + mode_data[1] + " (" + str(int(mode_data[1], 16)) + " mV)"
    print "\t\tIDD Nominal:\t" + mode_data[2] + " (" + str(int(mode_data[2], 16)) + " mA)"
    print "\t\tVCS Nominal:\t" + mode_data[3] + " (" + str(int(mode_data[3], 16)) + " mV)"
    print "\t\tICS Nominal:\t" + mode_data[4] + " (" + str(int(mode_data[4], 16)) + " mA)"

def show_poundv_bucket_power_data(power_data, friendly_name):
    print "\t" + friendly_name + ":"
    print "\t\tPower 1:\t" + power_data[0] + " (" + str(int(power_data[0], 16)) + " W)"
    print "\t\tPower 2:\t" + power_data[1] + " (" + str(int(power_data[0], 16)) + " W)"

def parse_poundv_bucket(bucket_data):
    modes = map(''.join, zip(*[iter(bucket_data[2:])]*20))
    id = bucket_data[:2]
    nominal = map(''.join, zip(*[iter(modes[0])]*4))
    powersave = map(''.join, zip(*[iter(modes[1])]*4))
    turbo = map(''.join, zip(*[iter(modes[2])]*4))
    ultraturbo = map(''.join, zip(*[iter(modes[3])]*4))
    powerbus = map(''.join, zip(*[iter(modes[4])]*4))
    sortpower = map(''.join, zip(*[iter(modes[5])]*4))

    return id, nominal, powersave, turbo, ultraturbo, powerbus, sortpower

def assemble_poundv_bucket(id, nominal, powersave, turbo, ultraturbo, powerbus, sortpower):
    modes_reassembled = ["", "", "", "", "", ""]
    modes_reassembled[0] = "".join(nominal)
    modes_reassembled[1] = "".join(powersave)
    modes_reassembled[2] = "".join(turbo)
    modes_reassembled[3] = "".join(ultraturbo)
    modes_reassembled[4] = "".join(powerbus)
    modes_reassembled[5] = "".join(sortpower)

    new_bucket_data = id + "".join(modes_reassembled)
    return new_bucket_data

source_bucket = int(sys.argv[1]) - 1
destination_bucket = int(sys.argv[2]) - 1
new_powerbus_mhz = int(sys.argv[3])
new_ultraturbo_mhz = int(sys.argv[4])
voltage_multiplier = float(sys.argv[5])
raw_data = sys.argv[6]

# Rated limit plus safety margin
#max_voltage = 1098

# Absolute maximum process limit
# Hardware damage WILL occur above this value!
max_voltage = 1150

if (source_bucket < 0) or (source_bucket > 5):
    print "[ERROR] Invalid source bucket specified"
    sys.exit(1)

if (destination_bucket < 0) or (destination_bucket > 5):
    print "[ERROR] Invalid destination bucket specified"
    sys.exit(1)

if source_bucket == destination_bucket:
    print "[ERROR] Cannot copy to same destination bucket as origin bucket"
    sys.exit(1)

# #V buckets start at offset 4, and run for 61 bytes each
# 6 buckets are defined
bucket = ["", "", "", "", "", ""]
header = raw_data[:8]
version = header[:2]
bucket[0] = raw_data[8:130]
bucket[1] = raw_data[130:252]
bucket[2] = raw_data[252:374]
bucket[3] = raw_data[374:496]
bucket[4] = raw_data[496:618]
bucket[5] = raw_data[618:740]

print "#V data block update"
print "=========================================="
print "Header:\t\t" + header
print "Version:\t" + str(int(version, 16))
print ""
for index in range (0, 5):
    if bucket[index][2:].startswith("0000"):
        continue

    if len(bucket[index][2:]) != 120:
        if destination_bucket == (index + 1):
            print "[ERROR] Source bucket invalid"
            sys.exit(1)
        print "Skipping invalid bucket " + str(index + 1)
        continue

    print "Bucket " + str(index + 1) + ":\t" + bucket[index]

    id, nominal, powersave, turbo, ultraturbo, powerbus, sortpower = parse_poundv_bucket(bucket[index])

    show_poundv_bucket_mode_data(powersave, "Powersave")
    show_poundv_bucket_mode_data(nominal, "Nominal")
    show_poundv_bucket_mode_data(turbo, "Turbo")
    show_poundv_bucket_mode_data(ultraturbo, "Ultra Turbo")
    show_poundv_bucket_mode_data(powerbus, "PowerBus")
    show_poundv_bucket_power_data(sortpower, "Sort Power")

    print ""

print "Copying and adjusting data from bucket " + str(source_bucket + 1) + " to bucket " + str(destination_bucket + 1)
if bucket[source_bucket][2:].startswith("0000"):
    print "[ERROR] Source bucket data not valid"
    sys.exit(1)

id, nominal, powersave, turbo, ultraturbo, powerbus, sortpower = parse_poundv_bucket(bucket[source_bucket])
new_id = format(destination_bucket + 1, '02x')
ultraturbo_ratio = float(new_ultraturbo_mhz) / int(ultraturbo[0], 16)
print "\tUltraturbo ratio:\t" + str(ultraturbo_ratio)
ultraturbo[0] = format(int(new_ultraturbo_mhz), '04x')
turbo[0] = format(int(int(turbo[0], 16) * ultraturbo_ratio), '04x')
nominal[0] = format(int(int(nominal[0], 16) * ultraturbo_ratio), '04x')
powersave[0] = format(int(int(powersave[0], 16) * ultraturbo_ratio), '04x')
powerbus[0] = format(new_powerbus_mhz, '04x')
new_voltage = voltage_multiplier * int(ultraturbo[1], 16)
if (new_voltage > max_voltage):
    new_voltage = max_voltage
ultraturbo[1] = format(int(new_voltage), '04x')
new_voltage = voltage_multiplier * int(turbo[1], 16)
if (new_voltage > max_voltage):
    new_voltage = max_voltage
turbo[1] = format(int(new_voltage), '04x')
new_voltage = voltage_multiplier * int(nominal[1], 16)
if (new_voltage > max_voltage):
    new_voltage = max_voltage
nominal[1] = format(int(new_voltage), '04x')
new_voltage = voltage_multiplier * int(powersave[1], 16)
if (new_voltage > max_voltage):
    new_voltage = max_voltage
powersave[1] = format(int(new_voltage), '04x')
new_voltage = voltage_multiplier * int(powerbus[1], 16)
if (new_voltage > max_voltage):
    new_voltage = max_voltage
powerbus[1] = format(int(new_voltage), '04x')
ultraturbo[2] = format(int(voltage_multiplier * int(ultraturbo[2], 16)), '04x')
turbo[2] = format(int(voltage_multiplier * int(turbo[2], 16)), '04x')
nominal[2] = format(int(voltage_multiplier * int(nominal[2], 16)), '04x')
powersave[2] = format(int(voltage_multiplier * int(powersave[2], 16)), '04x')
powerbus[2] = format(int(voltage_multiplier * int(powerbus[2], 16)), '04x')
bucket[destination_bucket] = assemble_poundv_bucket(new_id, nominal, powersave, turbo, ultraturbo, powerbus, sortpower)

print "\tModified bucket:\t" + bucket[destination_bucket]
show_poundv_bucket_mode_data(powersave, "Powersave")
show_poundv_bucket_mode_data(nominal, "Nominal")
show_poundv_bucket_mode_data(turbo, "Turbo")
show_poundv_bucket_mode_data(ultraturbo, "Ultra Turbo")
show_poundv_bucket_mode_data(powerbus, "PowerBus")
show_poundv_bucket_power_data(sortpower, "Sort Power")

new_bucket_data = header + "".join(bucket)

search_binstring = binascii.unhexlify(raw_data)
replace_binstring = binascii.unhexlify(new_bucket_data)

with open("search.bin", 'wb') as f:
    f.write(search_binstring)
with open("replace.bin", 'wb') as f:
    f.write(replace_binstring)

print ""
OpenPOWER on IntegriCloud