dis: power consumption annotations.
This commit is contained in:
parent
1959b8b895
commit
ca6a30b2e7
|
@ -50,7 +50,7 @@ int cmd_regs(char **arg)
|
|||
if (device_readmem(regs[0], code, len) < 0)
|
||||
return 0;
|
||||
|
||||
disassemble(regs[0], (uint8_t *)code, len);
|
||||
disassemble(regs[0], (uint8_t *)code, len, device_default->power_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -324,7 +324,7 @@ int cmd_dis(char **arg)
|
|||
}
|
||||
|
||||
reader_set_repeat("dis 0x%x 0x%x", offset + length, length);
|
||||
disassemble(offset, buf, length);
|
||||
disassemble(offset, buf, length, device_default->power_buf);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -371,7 +371,8 @@ static int do_isearch(address_t addr, address_t len,
|
|||
int count = dis_decode(mbuf + i, addr + i, len - i, &insn);
|
||||
|
||||
if (count >= 0 && isearch_match(&insn, q))
|
||||
disassemble(addr + i, mbuf + i, count);
|
||||
disassemble(addr + i, mbuf + i, count,
|
||||
device_default->power_buf);
|
||||
}
|
||||
|
||||
free(mbuf);
|
||||
|
|
|
@ -136,10 +136,10 @@ static int dis_format(const struct msp430_instruction *insn)
|
|||
insn->src_addr,
|
||||
insn->src_reg);
|
||||
|
||||
printc(",");
|
||||
len += printc(",");
|
||||
while (len < 15)
|
||||
len += printc(" ");
|
||||
printc(" ");
|
||||
len += printc(" ");
|
||||
}
|
||||
|
||||
/* Destination operand */
|
||||
|
@ -157,9 +157,12 @@ static int dis_format(const struct msp430_instruction *insn)
|
|||
return len;
|
||||
}
|
||||
|
||||
void disassemble(address_t offset, const uint8_t *data, int length)
|
||||
void disassemble(address_t offset, const uint8_t *data, int length,
|
||||
powerbuf_t power)
|
||||
{
|
||||
int first_line = 1;
|
||||
unsigned long long ua_total = 0;
|
||||
int samples_total = 0;
|
||||
|
||||
while (length) {
|
||||
struct msp430_instruction insn = {0};
|
||||
|
@ -194,13 +197,39 @@ void disassemble(address_t offset, const uint8_t *data, int length)
|
|||
}
|
||||
|
||||
if (retval >= 0)
|
||||
dis_format(&insn);
|
||||
i = dis_format(&insn);
|
||||
|
||||
if (power) {
|
||||
unsigned long long ua;
|
||||
int samples;
|
||||
|
||||
while (i < 40) {
|
||||
printc(" ");
|
||||
i++;
|
||||
}
|
||||
|
||||
samples = powerbuf_get_by_mab(power, offset, &ua);
|
||||
if (samples) {
|
||||
printc(" ;; %.01f uA",
|
||||
(double)ua / (double)samples);
|
||||
ua_total += ua;
|
||||
samples_total += samples;
|
||||
}
|
||||
}
|
||||
|
||||
printc("\n");
|
||||
|
||||
offset += count;
|
||||
length -= count;
|
||||
data += count;
|
||||
}
|
||||
|
||||
if (power && samples_total)
|
||||
printc(";; Total over this block: "
|
||||
"%.01f uAs in %.01f ms (%.01f uA avg)\n",
|
||||
(double)(ua_total * power->interval_us) / 1000000.0,
|
||||
(double)(samples_total * power->interval_us) / 1000.0,
|
||||
(double)ua_total / (double)samples_total);
|
||||
}
|
||||
|
||||
void hexdump(address_t addr, const uint8_t *data, int data_len)
|
||||
|
@ -256,9 +285,9 @@ void show_regs(const address_t *regs)
|
|||
int print_address(address_t addr, char *out, int max_len)
|
||||
{
|
||||
char name[MAX_SYMBOL_LENGTH];
|
||||
address_t offset;
|
||||
address_t offset;
|
||||
|
||||
if (!stab_nearest(addr, name, sizeof(name), &offset)) {
|
||||
if (!stab_nearest(addr, name, sizeof(name), &offset)) {
|
||||
int len;
|
||||
if (offset)
|
||||
len = snprintf(out, max_len, "%s+0x%x", name, offset);
|
||||
|
@ -270,7 +299,7 @@ int print_address(address_t addr, char *out, int max_len)
|
|||
snprintf(out + len, max_len - len, " (%s)", demangled);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(out, max_len, "0x%04x", addr);
|
||||
return 0;
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
|
||||
#include "output.h"
|
||||
#include "util.h"
|
||||
#include "powerbuf.h"
|
||||
|
||||
/* Print colorized disassembly on command processor standard output */
|
||||
void disassemble(address_t addr, const uint8_t *buf, int len);
|
||||
void disassemble(address_t addr, const uint8_t *buf, int len,
|
||||
powerbuf_t power);
|
||||
|
||||
/* Print colorized hexdump on standard output */
|
||||
void hexdump(address_t addr, const uint8_t *buf, int len);
|
||||
|
|
152
util/powerbuf.c
152
util/powerbuf.c
|
@ -42,6 +42,12 @@ powerbuf_t powerbuf_new(unsigned int max_samples, unsigned int interval_us)
|
|||
|
||||
pb->mab = malloc(sizeof(pb->mab[0]) * max_samples);
|
||||
if (!pb->mab) {
|
||||
free(pb->current_ua);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pb->sorted = malloc(sizeof(pb->sorted[0]) * max_samples);
|
||||
if (!pb->sorted) {
|
||||
free(pb->current_ua);
|
||||
free(pb->mab);
|
||||
return NULL;
|
||||
|
@ -60,6 +66,7 @@ void powerbuf_free(powerbuf_t pb)
|
|||
{
|
||||
free(pb->current_ua);
|
||||
free(pb->mab);
|
||||
free(pb->sorted);
|
||||
free(pb);
|
||||
}
|
||||
|
||||
|
@ -67,6 +74,7 @@ void powerbuf_clear(powerbuf_t pb)
|
|||
{
|
||||
pb->session_head = pb->session_tail = 0;
|
||||
pb->current_head = pb->current_tail = 0;
|
||||
pb->sort_valid = 0;
|
||||
}
|
||||
|
||||
static unsigned int session_length(powerbuf_t pb, unsigned int idx)
|
||||
|
@ -264,6 +272,8 @@ void powerbuf_add_samples(powerbuf_t pb, unsigned int count,
|
|||
mab += cont_len;
|
||||
count -= cont_len;
|
||||
}
|
||||
|
||||
pb->sort_valid = 0;
|
||||
}
|
||||
|
||||
address_t powerbuf_last_mab(powerbuf_t pb)
|
||||
|
@ -277,3 +287,145 @@ address_t powerbuf_last_mab(powerbuf_t pb)
|
|||
|
||||
return pb->mab[last];
|
||||
}
|
||||
|
||||
static void sift_down(powerbuf_t pb, int start, int end)
|
||||
{
|
||||
int root = start;
|
||||
|
||||
while (root * 2 + 1 <= end) {
|
||||
int left_child = root * 2 + 1;
|
||||
int biggest = root;
|
||||
unsigned int temp;
|
||||
|
||||
/* Find the largest of
|
||||
* (root, left child, right child)
|
||||
*/
|
||||
if (pb->mab[pb->sorted[biggest]] <
|
||||
pb->mab[pb->sorted[left_child]])
|
||||
biggest = left_child;
|
||||
if (left_child + 1 <= end &&
|
||||
(pb->mab[pb->sorted[biggest]] <
|
||||
pb->mab[pb->sorted[left_child + 1]]))
|
||||
biggest = left_child + 1;
|
||||
|
||||
/* If no changes are needed, the heap property is ok and
|
||||
* we can stop.
|
||||
*/
|
||||
if (biggest == root)
|
||||
break;
|
||||
|
||||
/* Swap the root with its largest child */
|
||||
temp = pb->sorted[biggest];
|
||||
pb->sorted[biggest] = pb->sorted[root];
|
||||
pb->sorted[root] = temp;
|
||||
|
||||
/* Continue to push down the old root (now a child) */
|
||||
root = biggest;
|
||||
}
|
||||
}
|
||||
|
||||
static void heapify(powerbuf_t pb, int num_samples)
|
||||
{
|
||||
int start = (num_samples - 2) / 2;
|
||||
|
||||
while (start >= 0) {
|
||||
sift_down(pb, start, num_samples - 1);
|
||||
start--;
|
||||
}
|
||||
}
|
||||
|
||||
static void heap_extract(powerbuf_t pb, int num_samples)
|
||||
{
|
||||
int end = num_samples - 1;
|
||||
|
||||
while (end > 0) {
|
||||
unsigned int temp;
|
||||
|
||||
/* Swap the top of the heap with the end of the array,
|
||||
* and shrink the heap.
|
||||
*/
|
||||
temp = pb->sorted[0];
|
||||
pb->sorted[0] = pb->sorted[end];
|
||||
pb->sorted[end] = temp;
|
||||
end--;
|
||||
|
||||
/* Fix up the heap (push down the new root) */
|
||||
sift_down(pb, 0, end);
|
||||
}
|
||||
}
|
||||
|
||||
void powerbuf_sort(powerbuf_t pb)
|
||||
{
|
||||
const unsigned int num_samples =
|
||||
(pb->current_head + pb->max_samples - pb->current_tail) %
|
||||
pb->max_samples;
|
||||
unsigned int i;
|
||||
|
||||
if (pb->sort_valid)
|
||||
return;
|
||||
|
||||
/* Prepare an index list */
|
||||
for (i = 0; i < num_samples; i++)
|
||||
pb->sorted[i] = (pb->current_tail + i) % pb->max_samples;
|
||||
|
||||
if (num_samples < 2) {
|
||||
pb->sort_valid = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
heapify(pb, num_samples);
|
||||
heap_extract(pb, num_samples);
|
||||
pb->sort_valid = 1;
|
||||
}
|
||||
|
||||
/* Find the index within the sorted index of the first sample with an
|
||||
* MAB >= the given mab parameter.
|
||||
*/
|
||||
static int find_mab_ge(powerbuf_t pb, address_t mab)
|
||||
{
|
||||
const int num_samples =
|
||||
(pb->current_head + pb->max_samples - pb->current_tail) %
|
||||
pb->max_samples;
|
||||
int low = 0;
|
||||
int high = num_samples - 1;
|
||||
|
||||
while (low <= high) {
|
||||
int mid = (low + high) / 2;
|
||||
|
||||
if (pb->mab[pb->sorted[mid]] < mab)
|
||||
low = mid + 1;
|
||||
else if ((mid <= 0) || (pb->mab[pb->sorted[mid - 1]] < mab))
|
||||
return mid;
|
||||
else
|
||||
high = mid - 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int powerbuf_get_by_mab(powerbuf_t pb, address_t mab,
|
||||
unsigned long long *sum_ua)
|
||||
{
|
||||
const unsigned int num_samples =
|
||||
(pb->current_head + pb->max_samples - pb->current_tail) %
|
||||
pb->max_samples;
|
||||
int i;
|
||||
int count = 0;
|
||||
|
||||
if (!pb->sort_valid)
|
||||
powerbuf_sort(pb);
|
||||
|
||||
i = find_mab_ge(pb, mab);
|
||||
if (i < 0)
|
||||
return 0;
|
||||
|
||||
*sum_ua = 0;
|
||||
|
||||
while ((i < num_samples) && (pb->mab[pb->sorted[i]] == mab)) {
|
||||
*sum_ua += pb->current_ua[pb->sorted[i]];
|
||||
count++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,17 @@ struct powerbuf {
|
|||
address_t *mab;
|
||||
unsigned int current_head;
|
||||
unsigned int current_tail;
|
||||
|
||||
/* Index by MAB. This is a flat array which points to indices
|
||||
* within current_ua/mab. The indices are sorted in order of
|
||||
* increasing MAB.
|
||||
*
|
||||
* Note that this array is invalidated by any modification to
|
||||
* the sample buffers. You need to call powerbuf_sort() before
|
||||
* accessing it.
|
||||
*/
|
||||
int sort_valid;
|
||||
unsigned int *sorted;
|
||||
};
|
||||
|
||||
typedef struct powerbuf *powerbuf_t;
|
||||
|
@ -120,4 +131,16 @@ void powerbuf_add_samples(powerbuf_t pb, unsigned int count,
|
|||
/* Retrieve the last known MAB for this session, or 0 if none exists. */
|
||||
address_t powerbuf_last_mab(powerbuf_t pb);
|
||||
|
||||
/* Prepare the sorted MAB index. */
|
||||
void powerbuf_sort(powerbuf_t pb);
|
||||
|
||||
/* Obtain charge consumption data by MAB over all sessions. This
|
||||
* automatically calls powerbuf_sort() if necessary.
|
||||
*
|
||||
* Returns the number of samples found on success. The sum of all
|
||||
* current samples is written to the sum_ua argument.
|
||||
*/
|
||||
int powerbuf_get_by_mab(powerbuf_t pb, address_t mab,
|
||||
unsigned long long *sum_ua);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue