A.Olokhtonov
4 months ago
commit
432fd08944
6 changed files with 238 additions and 0 deletions
@ -0,0 +1,11 @@ |
|||||||
|
html, body { |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
|
||||||
|
body .main { |
||||||
|
height: 100%; |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<title>Nitka</title> |
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
||||||
|
|
||||||
|
<link rel="shortcut icon" href="icons/favicon.svg" id="favicon"> |
||||||
|
<link rel="stylesheet" type="text/css" href="default.css"> |
||||||
|
|
||||||
|
<!-- <link rel="preload" href="icons/picker.svg" as="image" type="image/svg+xml" /> --> |
||||||
|
|
||||||
|
<script type="text/javascript" src="index.js"></script> |
||||||
|
<script type="text/javascript" src="parse.js"></script> |
||||||
|
<script type="text/javascript" src="render.js"></script> |
||||||
|
<script type="text/javascript" src="input.js"></script> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div class="main"> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,5 @@ |
|||||||
|
document.addEventListener('DOMContentLoaded', main); |
||||||
|
|
||||||
|
function main() { |
||||||
|
init_listeners(); |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
function init_listeners() { |
||||||
|
document.querySelector('.main').addEventListener('dragover', cancel); |
||||||
|
document.querySelector('.main').addEventListener('drop', drop); |
||||||
|
} |
||||||
|
|
||||||
|
function cancel(e) { |
||||||
|
e.preventDefault(); |
||||||
|
e.stopPropagation(); |
||||||
|
} |
||||||
|
|
||||||
|
function drop(e) { |
||||||
|
e.preventDefault(); |
||||||
|
|
||||||
|
if (e.dataTransfer.files.length !== 1) { |
||||||
|
console.error('Only one file at once, please!'); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
const file = e.dataTransfer.files[0]; |
||||||
|
const fr = new FileReader(); |
||||||
|
|
||||||
|
const upload_failed = () => { |
||||||
|
console.error('Upload failed'); |
||||||
|
}; |
||||||
|
|
||||||
|
const upload_started = () => { |
||||||
|
console.log('Upload started'); |
||||||
|
}; |
||||||
|
|
||||||
|
const upload_finished = () => { |
||||||
|
const text = fr.result; |
||||||
|
console.log('Finished. String length:', text.length); |
||||||
|
parse(text); |
||||||
|
}; |
||||||
|
|
||||||
|
const upload_progress = (e) => { |
||||||
|
if (e.lengthComputable) { |
||||||
|
const percent = Math.floor(e.loaded / e.total * 100); |
||||||
|
console.log(`Progress: ${percent}%`); |
||||||
|
} else { |
||||||
|
console.log('Progress: unknown'); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
fr.addEventListener('abort', upload_failed); |
||||||
|
fr.addEventListener('error', upload_failed); |
||||||
|
fr.addEventListener('load', upload_finished); |
||||||
|
fr.addEventListener('loadstart', upload_started); |
||||||
|
fr.addEventListener('progress', upload_progress); |
||||||
|
|
||||||
|
fr.readAsText(file); |
||||||
|
} |
@ -0,0 +1,147 @@ |
|||||||
|
function parse(text) { |
||||||
|
// https://github.com/shioyadan/Konata/blob/master/docs/kanata-log-format.md
|
||||||
|
|
||||||
|
const before = performance.now(); |
||||||
|
|
||||||
|
let line_start = 0; |
||||||
|
let line_index = 0; |
||||||
|
|
||||||
|
//console.log(text);
|
||||||
|
|
||||||
|
for (let i = 0; i < text.length; ++i) { |
||||||
|
const c = text[i]; |
||||||
|
|
||||||
|
if (c === '\n') { |
||||||
|
// TODO: speed
|
||||||
|
const line_copy = text.substring(line_start, i); |
||||||
|
const line_parts = line_copy.split(/\s+/); |
||||||
|
|
||||||
|
if (line_parts.length === 0) { |
||||||
|
console.error('Parser error: empty line'); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
const command = line_parts[0]; |
||||||
|
switch (command) { |
||||||
|
case 'Kanata': { |
||||||
|
if (!assert_arglen(line_parts, 1, 'Kanata')) return false; |
||||||
|
|
||||||
|
const version = Number(line_parts[1]); |
||||||
|
if (version !== 4) { |
||||||
|
console.error('Parser error: only Kanata traces version 4 are supported'); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'C=': { |
||||||
|
if (!assert_arglen(line_parts, 1, 'C=')) return false; |
||||||
|
|
||||||
|
const cycles = Number(line_parts[1]); |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'C': { |
||||||
|
if (!assert_arglen(line_parts, 1, 'C')) return false; |
||||||
|
|
||||||
|
const cycles = Number(line_parts[1]); |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'I': { |
||||||
|
if (!assert_arglen(line_parts, 3, 'I')) return false; |
||||||
|
|
||||||
|
const insn_id_in_file = Number(line_parts[1]); |
||||||
|
const insn_id_in_sim = Number(line_parts[2]); |
||||||
|
const thread_id = Number(line_parts[3]); |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'L': { |
||||||
|
if (!assert_arglenmin(line_parts, 3, 'L')) return false; |
||||||
|
|
||||||
|
const id = Number(line_parts[1]); |
||||||
|
const type = Number(line_parts[2]); |
||||||
|
const text = line_parts.slice(3).join(' '); // TODO: preserve spacing, newlines
|
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'S': { |
||||||
|
if (!assert_arglen(line_parts, 3, 'S')) return false; |
||||||
|
|
||||||
|
const id = Number(line_parts[1]); |
||||||
|
const lane = Number(line_parts[2]); |
||||||
|
const stage = line_parts[3]; |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'E': { |
||||||
|
if (!assert_arglen(line_parts, 3, 'E')) return false; |
||||||
|
|
||||||
|
const id = Number(line_parts[1]); |
||||||
|
const lane = Number(line_parts[2]); |
||||||
|
const stage = line_parts[3]; |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'R': { |
||||||
|
if (!assert_arglen(line_parts, 3, 'R')) return false; |
||||||
|
|
||||||
|
const id = Number(line_parts[1]); |
||||||
|
const retire_id = Number(line_parts[2]); |
||||||
|
const type = Number(line_parts[3]); |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
case 'W': { |
||||||
|
if (!assert_arglen(line_parts, 3, 'W')) return false; |
||||||
|
|
||||||
|
const consumer_id = Number(line_parts[1]); |
||||||
|
const producer_id = Number(line_parts[2]); |
||||||
|
const type = Number(line_parts[3]); |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
default: { |
||||||
|
console.error('Parser error: unexpected command', command); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
//console.log(command);
|
||||||
|
|
||||||
|
line_start = i + 1; |
||||||
|
line_index += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const after = performance.now(); |
||||||
|
|
||||||
|
console.log(`Parsed in ${Math.round(after - before)}ms`); |
||||||
|
} |
||||||
|
|
||||||
|
function assert_arglen(args, arglen, command) { |
||||||
|
if (args.length !== arglen + 1) { |
||||||
|
console.error(`Parser error: command ${command} requires ${arglen} argument(s)`); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
function assert_arglenmin(args, arglen, command) { |
||||||
|
if (args.length < arglen + 1) { |
||||||
|
console.error(`Parser error: command ${command} requires at least ${arglen} argument(s)`); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
Loading…
Reference in new issue