@em-foundation/emscope 25.3.0 → 25.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +14 -3
- package/dist/emscope +59 -5
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
<img src="docs/images/logo.png" alt="EM•Scope Logo" width="400">
|
|
3
|
+
</p>
|
|
4
|
+
<br>
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="docs/images/tagline.png" alt="EM•Scope TagLine" width="750">
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
-----
|
|
10
|
+
|
|
11
|
+
The **EM•Scope** tool streamlines the capture, analysis, display, and delivery of real-time power-consumption measurements – used to characterize the overall energy efficiency of resource-constrained embedded systems.  To encourage benchmarks for different HW/SW configurations performing comparable tasks, **EM•Scope** introduces a novel metric for quantifying energy efficiency – the **EM•erald**.
|
|
12
|
+
|
|
13
|
+
<p align="right">
|
|
14
|
+
<a href="https://github.com/em-foundation/emscope/blob/docs-stable/docs/ReadMore.md">read more<b> ➦</b></a>
|
|
15
|
+
</p>
|
package/dist/emscope
CHANGED
|
@@ -13167,6 +13167,7 @@ async function findDevices() {
|
|
|
13167
13167
|
}
|
|
13168
13168
|
}
|
|
13169
13169
|
fail("no PPK2 analyzer found", res.length == 0);
|
|
13170
|
+
res.sort();
|
|
13170
13171
|
return res;
|
|
13171
13172
|
}
|
|
13172
13173
|
function parseMods(mods) {
|
|
@@ -13509,8 +13510,9 @@ function exec4(opts) {
|
|
|
13509
13510
|
const cap = Capture.load(opts.capture);
|
|
13510
13511
|
fail(`no prior analysis: run 'emscope scan ...'`, cap.analysis === void 0);
|
|
13511
13512
|
const aobj = cap.analysis;
|
|
13513
|
+
const json2 = !!opts.json;
|
|
13512
13514
|
if (opts.eventInfo) {
|
|
13513
|
-
printEventInfo(cap, aobj.events);
|
|
13515
|
+
json2 ? printEventInfoJson(cap, aobj.events) : printEventInfo(cap, aobj.events);
|
|
13514
13516
|
return;
|
|
13515
13517
|
}
|
|
13516
13518
|
if (opts.jlsFile) {
|
|
@@ -13518,16 +13520,16 @@ function exec4(opts) {
|
|
|
13518
13520
|
return;
|
|
13519
13521
|
}
|
|
13520
13522
|
if (opts.sleepInfo) {
|
|
13521
|
-
printSleepInfo(cap, aobj.sleep);
|
|
13523
|
+
json2 ? printSleepInfoJson(cap, aobj.sleep) : printSleepInfo(cap, aobj.sleep);
|
|
13522
13524
|
return;
|
|
13523
13525
|
}
|
|
13524
13526
|
if (opts.whatIf !== void 0) {
|
|
13525
13527
|
const ev_rate = opts.whatIf === true ? 1 : opts.whatIf;
|
|
13526
|
-
printResults(cap, aobj, ev_rate, opts.score);
|
|
13528
|
+
json2 ? printResultsJson(cap, aobj, ev_rate) : printResults(cap, aobj, ev_rate, opts.score);
|
|
13527
13529
|
return;
|
|
13528
13530
|
}
|
|
13529
13531
|
if (opts.score) {
|
|
13530
|
-
printResults(cap, aobj, 1, true);
|
|
13532
|
+
json2 ? printResultsJson(cap, aobj, 1) : printResults(cap, aobj, 1, true);
|
|
13531
13533
|
return;
|
|
13532
13534
|
}
|
|
13533
13535
|
fail(`no options found: run 'emscope view -h'`);
|
|
@@ -13577,6 +13579,27 @@ function printEventInfo(cap, markers) {
|
|
|
13577
13579
|
infoMsg("----");
|
|
13578
13580
|
infoMsg(`average energy over ${markers.length} event(s): ${uJoules(avg)}`);
|
|
13579
13581
|
}
|
|
13582
|
+
function printEventInfoJson(cap, markers) {
|
|
13583
|
+
const events = markers.map((m, i) => {
|
|
13584
|
+
const energy = cap.energyWithin(m);
|
|
13585
|
+
const duration = cap.current_sig.offToSecs(m.width);
|
|
13586
|
+
const time = cap.current_sig.offToSecs(m.offset);
|
|
13587
|
+
return {
|
|
13588
|
+
id: String.fromCharCode("A".charCodeAt(0) + i),
|
|
13589
|
+
time,
|
|
13590
|
+
energy,
|
|
13591
|
+
duration
|
|
13592
|
+
};
|
|
13593
|
+
});
|
|
13594
|
+
const totalEnergy = events.reduce((sum, e) => sum + e.energy, 0);
|
|
13595
|
+
const avgEnergy = events.length > 0 ? totalEnergy / events.length : 0;
|
|
13596
|
+
console.log(JSON.stringify({
|
|
13597
|
+
type: "event_info",
|
|
13598
|
+
eventCount: events.length,
|
|
13599
|
+
averageEnergy: avgEnergy,
|
|
13600
|
+
events
|
|
13601
|
+
}));
|
|
13602
|
+
}
|
|
13580
13603
|
function printResults(cap, aobj, ev_rate, score_only) {
|
|
13581
13604
|
const sleep_pwr = aobj.sleep.avg * cap.avg_voltage;
|
|
13582
13605
|
score_only || infoMsg(`event period: ${secsToHms(ev_rate)}`);
|
|
@@ -13594,9 +13617,39 @@ function printResults(cap, aobj, ev_rate, score_only) {
|
|
|
13594
13617
|
score_only || infoMsg("----");
|
|
13595
13618
|
infoMsg(`${ems.toFixed(2)} EM\u2022eralds`);
|
|
13596
13619
|
}
|
|
13620
|
+
function printResultsJson(cap, aobj, ev_rate) {
|
|
13621
|
+
const sleep_pwr = aobj.sleep.avg * cap.avg_voltage;
|
|
13622
|
+
const egy_1s = cap.energyWithin(aobj.span) / cap.current_sig.offToSecs(aobj.span.width);
|
|
13623
|
+
const egy_1e = egy_1s - sleep_pwr * 1;
|
|
13624
|
+
const egy_1c = sleep_pwr * ev_rate + egy_1e;
|
|
13625
|
+
const egy_1d = egy_1c * 86400 / ev_rate;
|
|
13626
|
+
const egy_1m = egy_1d * 30;
|
|
13627
|
+
const ems = 2400 / egy_1m;
|
|
13628
|
+
console.log(JSON.stringify({
|
|
13629
|
+
type: "score",
|
|
13630
|
+
emeralds: parseFloat(ems.toFixed(2)),
|
|
13631
|
+
cycleRate: ev_rate,
|
|
13632
|
+
sleepCurrent: aobj.sleep.avg,
|
|
13633
|
+
sleepPower: sleep_pwr,
|
|
13634
|
+
voltage: cap.avg_voltage,
|
|
13635
|
+
eventEnergy: egy_1e,
|
|
13636
|
+
energyPerCycle: egy_1c,
|
|
13637
|
+
energyPerDay: egy_1d,
|
|
13638
|
+
energyPerMonth: egy_1m
|
|
13639
|
+
}));
|
|
13640
|
+
}
|
|
13597
13641
|
function printSleepInfo(cap, si) {
|
|
13598
13642
|
infoMsg(`sleep current = ${uAmps(si.avg).trim()} @ ${cap.avg_voltage.toFixed(1)} V, standard deviation = ${uAmps(si.std).trim()}`);
|
|
13599
13643
|
}
|
|
13644
|
+
function printSleepInfoJson(cap, si) {
|
|
13645
|
+
console.log(JSON.stringify({
|
|
13646
|
+
type: "sleep_info",
|
|
13647
|
+
sleepCurrent: si.avg,
|
|
13648
|
+
standardDeviation: si.std,
|
|
13649
|
+
voltage: cap.avg_voltage,
|
|
13650
|
+
sleepPower: si.avg * cap.avg_voltage
|
|
13651
|
+
}));
|
|
13652
|
+
}
|
|
13600
13653
|
|
|
13601
13654
|
// node_modules/commander/esm.mjs
|
|
13602
13655
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -13621,7 +13674,7 @@ var VERS = version();
|
|
|
13621
13674
|
var CMD = new Command("emscope").option("-C, --capture-glob [name pattern]", `apply this command to each matching child capture directory (default "**")`).version(VERS);
|
|
13622
13675
|
CMD.command("grab").description("record power signals with an attached capture device").option(CAP[0], CAP[1], CAP[2]).option("-d --duration <value>", "capture duration in seconds", parseFloat, 3).option("-J --js220", "use a Joulescope JS220 device").option("-P --ppk2", "use a Nordic PPK2 device").addOption(new Option("-A --ampere-mode", "enable PPK ampere mode").conflicts(["sourceMode", "js220"])).addOption(new Option("-S --source-mode", "enable PPK source mode").default(true).conflicts(["ampereMode", "js220"])).addOption(new Option("-p, --ppk2-supply [voltage]", "supply JS220 voltage from a PPK").argParser(parseFloat).conflicts("ppk2")).addOption(new Option("-v, --voltage [value]", "source voltage").argParser(parseFloat).default(3.3).conflicts("js220")).action((opts, cmd) => execCmd(exec3, opts, cmd.parent.opts()));
|
|
13623
13676
|
CMD.command("scan").description("analyze captured data and locate active events").option(CAP[0], CAP[1], CAP[2]).option("-d, --min-duration <milliseconds>", "remove events whose duration is under a threshold", parseFloat).option("-e, --min-energy <microJoules>", "remove events whose energy is under a threshold", parseFloat).option("-g, --gap <milliseconds>", "combine adjacent events whose gap is under a threshold", parseFloat).option("-t --trim <event count>", "remove extra events", parseFloat).option("--refresh", "(re-)scan using the last set of options").action((opts, cmd) => execCmd(exec, opts, cmd.parent.opts()));
|
|
13624
|
-
CMD.command("view").description("present captured data in different formats").option(CAP[0], CAP[1], CAP[2]).option("-e --event-info", "characterize power consumption when active").option("-j --jls-file [event ID]", "generate a Joulescope .jls file containing events").option("-s --sleep-info", "characterize power consumption when inactive").option("-w --what-if [event period]", `extrapolate results for a given event period (default: '00:00:01')`, parseHms).option("--score", "only print the EM\u2022eralds benchmark score").action((opts, cmd) => execCmd(exec4, opts, cmd.parent.opts()));
|
|
13677
|
+
CMD.command("view").description("present captured data in different formats").option(CAP[0], CAP[1], CAP[2]).option("-e --event-info", "characterize power consumption when active").option("-j --jls-file [event ID]", "generate a Joulescope .jls file containing events").option("-s --sleep-info", "characterize power consumption when inactive").option("-w --what-if [event period]", `extrapolate results for a given event period (default: '00:00:01')`, parseHms).option("--score", "only print the EM\u2022eralds benchmark score").option("--json", "output results as JSON (machine-readable)").action((opts, cmd) => execCmd(exec4, opts, cmd.parent.opts()));
|
|
13625
13678
|
CMD.command("pack").description(`bundle captured data into an 'emscope.zip' file`).option(CAP[0], CAP[1], CAP[2]).option("-a --about-file", `update the 'ABOUT.md' file only`).option("-s,--status", `status of the 'emscope.zip' file`).option("-u --unpack", `deflate the 'emscope.zip' file for local use`).option("-z --zip-file", `generate the 'emscope.zip' file`).option("--restore", `restores the 'emscope.zip' LFS descriptor (debug only)`).action((opts, cmd) => execCmd(exec2, opts, cmd.parent.opts()));
|
|
13626
13679
|
try {
|
|
13627
13680
|
CMD.parse(process.argv);
|
|
@@ -13634,3 +13687,4 @@ try {
|
|
|
13634
13687
|
js-yaml/dist/js-yaml.mjs:
|
|
13635
13688
|
(*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT *)
|
|
13636
13689
|
*/
|
|
13690
|
+
//# sourceMappingURL=emscope.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@em-foundation/emscope",
|
|
3
|
-
"version": "25.
|
|
3
|
+
"version": "25.4.0",
|
|
4
4
|
"description": "benchmark energy efficiency in resource-constrained embedded systems",
|
|
5
5
|
"bin": {
|
|
6
6
|
"emscope": "dist/emscope"
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
"author": "The EM Foundation",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"preferGlobal": true,
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
32
35
|
"bugs": {
|
|
33
36
|
"url": "https://github.com/em-foundation/emscope/issues"
|
|
34
37
|
},
|