Skip to content

Commit c283234

Browse files
Merge branch 'main' into user-guide-ToC
2 parents 735b7b0 + 95c5fe1 commit c283234

File tree

11 files changed

+350
-267
lines changed

11 files changed

+350
-267
lines changed

backend/restapi_server.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#
55
import argparse
66
import os
7+
import signal
78
import sys
89
from flask import Flask, request, jsonify
910
from flasgger import Swagger
@@ -34,7 +35,7 @@ def main():
3435
args = parser.parse_args()
3536

3637
# setup app logger
37-
log_setup(filename=args.logfile, max_bytes=args.maxbytes*1024, backup_count=args.backupcount)
38+
log_setup(filename=args.logfile, max_bytes=args.maxbytes * 1024, backup_count=args.backupcount)
3839

3940
# Check if the device_file exists
4041
if os.path.exists(args.device_file) == False:
@@ -54,7 +55,7 @@ def main():
5455
"swagger": "2.0",
5556
"info": {
5657
"title": "RPE Backend API",
57-
"description": "The RPE Backend APIs which consumed by the RPE frontend for power and thermal estimation of the Rapid Silicon devices.",
58+
"description": "The RPE Backend APIs which are consumed by the RPE frontend for power and thermal estimation of the Rapid Silicon devices.",
5859
"version": "0.1.0"
5960
}
6061
}
@@ -81,6 +82,25 @@ def after_request(response):
8182
log(f"{request.method} {request.url} {response.status_code} - DONE")
8283
return response
8384

85+
# Graceful shutdown function
86+
def shutdown_server():
87+
log("Shutting down server...")
88+
func = request.environ.get('werkzeug.server.shutdown')
89+
if func is not None:
90+
func()
91+
else:
92+
log("Server shutdown function not found.", RsLogLevel.ERROR)
93+
94+
# Signal handler for smooth shutdown
95+
def signal_handler(signal_received, frame):
96+
log(f"Signal {signal_received} received, initiating shutdown...")
97+
shutdown_server()
98+
sys.exit(0)
99+
100+
# Register the signal handler for SIGINT (Ctrl+C) and SIGTERM
101+
signal.signal(signal.SIGINT, signal_handler)
102+
signal.signal(signal.SIGTERM, signal_handler)
103+
84104
# log app server started
85105
log("App server is running...")
86106

cleanup.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
1-
const isWindows = process.platform === 'win32';
1+
const os = require('os');
2+
const platform = os.platform();
23

34
const kill = (process) => {
4-
if (isWindows) {
5-
const kill = require('tree-kill');
6-
kill(process.pid);
7-
} else {
8-
process.kill('SIGINT');
9-
}
5+
console.log(`Attempting to kill process with PID: ${process.pid}`);
6+
const { spawn } = require('child_process');
7+
if (platform === 'win32') {
8+
// used taskkill for Windows to terminate the process tree
9+
const taskKill = spawn('taskkill', ['/PID', process.pid, '/T', '/F']);
10+
taskKill.on('close', (code) => {
11+
if (code === 0) {
12+
console.log('Process killed successfully on Windows.');
13+
} else {
14+
console.error(`taskkill failed with exit code: ${code}`);
15+
}
16+
});
17+
} else if (platform === 'darwin' || platform === 'linux') {
18+
const taskKill = spawn('kill', ['-9', process.pid]);
19+
taskKill.on('close', (code) => {
20+
if (code === 0) {
21+
console.log('Process killed successfully on Unix.');
22+
} else {
23+
console.error(`taskkill failed with exit code: ${code}`);
24+
}
25+
});
26+
} else {
27+
try {
28+
process.kill('SIGINT');
29+
console.log('SIGINT sent to process');
30+
} catch (error) {
31+
console.error(`Failed to send SIGINT: ${error.message}`);
32+
}
33+
}
1034
};
1135

1236
module.exports = { kill };

docs/source/user_guide/FPGA_index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
FPGA Input
33
=============
44

5-
This section will document FPGA input for Rapid Power Estimator.
65

76
To begin inputting FPGA information, the user must have an RTL design that they would like to run on an FPGA platform. For users who have used other FPGA vendors' EDA tools, they can directly enter the FPGA input using their estimated FPGA utilization.
87

@@ -77,4 +76,5 @@ Selecting the IO section displays an empty table, click the "Add" button above t
7776

7877
.. image:: figures/FPGA-figures-IO-input_IO_info2.JPG
7978

80-
Enter I/O port name, bus width, select clock, enter duty cycle, select IO direction & standard, drive strength (current in Amperes), slew rate, differential termination, pullup/pulldown resistors, data type, enter input enable rate, output enable rate, select synchronization & enter toggle rate
79+
Enter I/O port name, bus width, select clock, enter duty cycle, select IO direction & standard, drive strength (current in Amperes), slew rate, differential termination, pullup/pulldown resistors, data type, enter input enable rate, output enable rate, select synchronization & enter toggle rate
80+

docs/source/user_guide/SoC_index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,4 @@ Enable/disable each channel using the checkboxes under the Enable column, then c
105105
.. image:: figures/SoC-figures-DMA-put_DMA_info.JPG
106106

107107
For each channel, select a source & destination, typically a peripheral will be connected to a memory or vice-versa. Then select the active state, read/write rate & toggle rate.
108+

main.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,10 @@ app.whenReady().then(() => {
317317
});
318318
});
319319

320-
app.on('window-all-closed', () => {
320+
app.on("before-quit", function () {
321321
kill(serverProcess);
322+
})
323+
324+
app.on('window-all-closed', () => {
322325
if (process.platform !== 'darwin') app.quit();
323326
});

tests/e2e/acpu.test.js

Lines changed: 0 additions & 37 deletions
This file was deleted.

tests/e2e/bcpu.test.js

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,38 @@
1-
// const { _electron: electron } = require('playwright');
2-
// const { test, expect } = require('@playwright/test');
3-
4-
// test('Launch Electron app, select device MPW1 Gemini, and click on BCPU block', async () => {
5-
// const app = await electron.launch({ args: ['main.js'], headless: false });
6-
7-
// const window = await app.firstWindow();
8-
9-
// // selecting MPW1 Gemini from device dropdown
10-
// const deviceDropdown = await window.waitForSelector('#deviceId');
11-
// await deviceDropdown.selectOption('MPW1');
12-
// await window.waitForTimeout(2000); // wait for UI update
13-
14-
// // click on the BCPU block
15-
// const bcpuSelector = '#app > div > div.top-row-container > div.main-table-container.main-border > div.top-l2 > div.top-l2-col1 > div.top-l2-col1-row1 > div:nth-child(2) > div';
16-
// await window.waitForSelector(bcpuSelector);
17-
// await window.click(bcpuSelector);
18-
19-
// // click on "Add" button
20-
// const addButtonSelector = '#app > div > div.table-container.main-border > div > div.cpu-container > div.table-wrapper > button';
21-
// await window.waitForSelector(addButtonSelector, { state: 'visible' });
22-
// await window.click(addButtonSelector);
23-
24-
// // click on "OK" button
25-
// const okButtonSelector = 'button.ant-btn-primary';
26-
// await window.waitForSelector(okButtonSelector, { state: 'visible' });
27-
// await window.click(okButtonSelector);
28-
29-
// // click on Peripherals tab
30-
// const peripheralsTabSelector = '#app > div > div.top-row-container > div.main-table-container.main-border > div.top-l2 > div.top-l2-col1 > div:nth-child(3) > div > div:nth-child(2) > div:nth-child(2) > div.periph-internal-font-header';
31-
// await window.waitForSelector(peripheralsTabSelector, { state: 'visible' });
32-
// await window.click(peripheralsTabSelector);
33-
34-
// // check SPI/QSPI block
35-
// const spiQspiCheckSelector = '#\\30';
36-
// await window.waitForSelector(spiQspiCheckSelector, { state: 'visible' });
37-
// await window.click(spiQspiCheckSelector);
38-
39-
// // waiting to observe result on UI
40-
// await window.waitForTimeout(5000);
41-
42-
// // closing RPE
43-
// await app.close();
44-
// });
1+
const { _electron: electron } = require('playwright');
2+
const { test, expect } = require('@playwright/test');
3+
4+
test('Launch Electron app, select device MPW1 Gemini, and click on BCPU block', async () => {
5+
const app = await electron.launch({ args: ['main.js'], headless: false });
6+
const window = await app.firstWindow();
7+
8+
// Selecting MPW1 Gemini from device dropdown
9+
const deviceDropdown = await window.waitForSelector('#deviceId');
10+
await deviceDropdown.selectOption('MPW1');
11+
12+
// Click on the BCPU block
13+
const bcpuSelector = '#app > div > div.top-row-container > div.main-table-container.main-border > div.top-l2 > div.top-l2-col1 > div.top-l2-col1-row1 > div:nth-child(2) > div';
14+
await window.click(bcpuSelector);
15+
16+
// Click on "Add" button
17+
const addButtonSelector = '#app > div > div.table-container.main-border > div > div.cpu-container > div.table-wrapper > button';
18+
await window.waitForSelector(addButtonSelector, { state: 'visible' });
19+
await window.click(addButtonSelector);
20+
21+
// Click on "OK" button
22+
const okButtonSelector = 'button.ant-btn-primary';
23+
await window.waitForSelector(okButtonSelector, { state: 'visible' });
24+
await window.click(okButtonSelector);
25+
26+
// Click on Peripherals tab
27+
const peripheralsTabSelector = '#app > div > div.top-row-container > div.main-table-container.main-border > div.top-l2 > div.top-l2-col1 > div:nth-child(3)';
28+
await window.click(peripheralsTabSelector);
29+
30+
// Check SPI/QSPI block
31+
const spiQspiCheckSelector = '#\\30';
32+
await window.click(spiQspiCheckSelector);
33+
34+
console.log('BCPU power verified.');
35+
36+
// Close the app
37+
await app.close();
38+
});

tests/e2e/clocking.test.js

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,51 @@
1-
// const { _electron: electron } = require('playwright');
2-
// const { test, expect } = require('@playwright/test');
3-
4-
// test('Launch Electron app, select device, toggle ACPU power, click Clocking, Add clock source, and submit form', async () => {
5-
// const app = await electron.launch({ args: ['main.js'] });
6-
// const window = await app.firstWindow();
7-
8-
// // Selecting the device (MPW1 Gemini)
9-
// const deviceDropdown = await window.waitForSelector('#deviceId');
10-
// await deviceDropdown.selectOption('MPW1');
11-
// await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait for 2 seconds
12-
13-
// // Selecting Clocking block
14-
// const clockingBlockSelector = '#app > div > div.top-row-container > div.main-table-container.main-border > div.top-l2 > div.top-l2-col2 > div.top-l2-col2-elem > div > div:nth-child(2) > div:nth-child(1) > div';
15-
// const clockingBlock = await window.waitForSelector(clockingBlockSelector);
16-
// await clockingBlock.click();
17-
// await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait for 2 seconds
18-
19-
// // Clicking on Add button
20-
// const addButtonSelector = '#app > div > div.table-container.main-border > div > div.power-and-table-wrapper > div.table-wrapper > button';
21-
// const addButton = await window.waitForSelector(addButtonSelector);
22-
// await addButton.click();
23-
// await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait for 2 seconds
24-
25-
// // Ensure modal is visible before interacting
26-
// const modalSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div';
27-
// await window.waitForSelector(modalSelector, { state: 'visible', timeout: 5000 }); // Wait for modal
28-
29-
// // Typing description as 'test'
30-
// const descriptionSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div > div:nth-child(1) > div > div.ant-modal-body > div > form > div:nth-child(2) > input[type=text]';
31-
// const descriptionInput = await window.waitForSelector(descriptionSelector);
32-
// await descriptionInput.click();
33-
// await descriptionInput.fill('test');
34-
// await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for 1 second
35-
36-
// // Typing Port/Signal name as 'test'
37-
// const portSignalSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div > div:nth-child(1) > div > div.ant-modal-body > div > form > div:nth-child(3) > input[type=text]';
38-
// const portSignalInput = await window.waitForSelector(portSignalSelector);
39-
// await portSignalInput.click();
40-
// await portSignalInput.fill('test');
41-
// await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for 1 second
42-
43-
// // Clicking OK to submit the form
44-
// const okButtonSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div > div:nth-child(1) > div > div.ant-modal-footer > button.ant-btn.css-dev-only-do-not-override-apn68.ant-btn-primary.ant-btn-color-primary.ant-btn-variant-solid';
45-
// const okButton = await window.waitForSelector(okButtonSelector);
46-
// await okButton.click();
47-
48-
// // Closing the test
49-
// await app.close();
50-
// });
1+
const { _electron: electron } = require('playwright');
2+
const { test, expect } = require('@playwright/test');
3+
4+
test('Launch Electron app, select device, toggle ACPU power, click Clocking, Add clock source, and submit form', async () => {
5+
const app = await electron.launch({ args: ['main.js'] });
6+
const window = await app.firstWindow();
7+
8+
// Selecting the device (MPW1 Gemini)
9+
const deviceDropdown = await window.waitForSelector('#deviceId');
10+
await deviceDropdown.selectOption('MPW1');
11+
await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait for 2 seconds
12+
13+
// Selecting Clocking block
14+
const clockingBlockSelector = '#app > div > div.top-row-container > div.main-table-container.main-border > div.top-l2 > div.top-l2-col2 > div.top-l2-col2-elem > div > div:nth-child(2) > div:nth-child(1) > div';
15+
const clockingBlock = await window.waitForSelector(clockingBlockSelector);
16+
await clockingBlock.click();
17+
await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait for 2 seconds
18+
19+
// Clicking on Add button
20+
const addButtonSelector = '#app > div > div.table-container.main-border > div > div.power-and-table-wrapper > div.table-wrapper > button';
21+
const addButton = await window.waitForSelector(addButtonSelector);
22+
await addButton.click();
23+
await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait for 2 seconds
24+
25+
// Ensure modal is visible before interacting
26+
const modalSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div';
27+
await window.waitForSelector(modalSelector, { state: 'visible', timeout: 5000 }); // Wait for modal
28+
29+
// Typing description as 'test'
30+
const descriptionSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div > div:nth-child(1) > div > div.ant-modal-body > div > form > div:nth-child(2) > input[type=text]';
31+
const descriptionInput = await window.waitForSelector(descriptionSelector);
32+
await descriptionInput.click();
33+
await descriptionInput.fill('test');
34+
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for 1 second
35+
36+
// Typing Port/Signal name as 'test'
37+
const portSignalSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div > div:nth-child(1) > div > div.ant-modal-body > div > form > div:nth-child(3) > input[type=text]';
38+
const portSignalInput = await window.waitForSelector(portSignalSelector);
39+
await portSignalInput.click();
40+
await portSignalInput.fill('test');
41+
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for 1 second
42+
43+
// Clicking OK to submit the form
44+
const okButtonSelector = 'body > div:nth-child(3) > div > div.ant-modal-wrap > div > div:nth-child(1) > div > div.ant-modal-footer > button.ant-btn.css-dev-only-do-not-override-49qm.ant-btn-primary.ant-btn-color-primary.ant-btn-variant-solid > span';
45+
const okButton = await window.waitForSelector(okButtonSelector);
46+
await okButton.click();
47+
48+
// Closing the test
49+
await app.close();
50+
});
5151

0 commit comments

Comments
 (0)