Skip to content

Commit f240780

Browse files
committed
Change the opacity for the accesses (heatmap), toggle background, split
With this commit the opacity is automatically changed to fit the maximum access and the current access. Additionally two toggle buttons were introduced, one to toggle either black or white background for the memory table, the other to toggle either the unified memory view or the split (into read and write) memory view.
1 parent bd4709b commit f240780

11 files changed

Lines changed: 165 additions & 41 deletions

File tree

html/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ This will currently create a `build` folder with an `index.html` file in it.
9090

9191
All packages used in `package.json` are listed here with a short explanation (in alphabetical order).
9292

93+
* `@iconify/icons-ic`
94+
* Add the `icons-ic` icon set for offline use. A list of all available icons can be found [here](https://icon-sets.iconify.design/ic/).
95+
* `@iconify/svelte`
96+
* Add a icon component of the `iconify` library which is usable in Svelte.
9397
* `@skeletonlabs/skeleton`
9498
* This is a UI framework which provides some pre-made components for svelte (like the drawer) and additionally dictates the default style, the official docs can be found [here](https://www.skeleton.dev/docs/why)
9599
* `@sveltejs/vite-plugin-svelte`
@@ -106,6 +110,8 @@ All packages used in `package.json` are listed here with a short explanation (in
106110
* Add ESLint (rule) support to TypeScript code.
107111
* `autoprefixer`
108112
* A PostCSS plugin to automatically add necessary browser prefixes to CSS, so that more browsers are supported.
113+
* `color2k`
114+
* A compact library for color manipulations. (Interpolate between colors, make them more transparent, and be able to output this as a color for CSS)
109115
* `esbuild`
110116
* Used by Vite for minification and transpilation. (Also supports features like tree shaking)
111117
* `eslint`

html/index.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
<meta name="viewport" content="width=device-width" />
66
</head>
77
<body data-theme="skeleton">
8-
<div style="display: contents" class="h-full overflow-hidden">
9-
<div id="app"></div>
10-
<script type="module" src="/src/main.ts"></script>
11-
</div>
8+
<script type="module" src="/src/main.ts"></script>
129
</body>
1310
</html>

html/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
"check": "svelte-check --tsconfig ./tsconfig.json"
1212
},
1313
"devDependencies": {
14+
"@iconify/icons-ic": "^1.2.13",
15+
"@iconify/svelte": "^3.0.1",
1416
"@skeletonlabs/skeleton": "^0.92.2",
1517
"@sveltejs/vite-plugin-svelte": "^2.0.2",
1618
"@tailwindcss/forms": "^0.5.3",
@@ -20,6 +22,7 @@
2022
"@typescript-eslint/eslint-plugin": "^5.48.2",
2123
"@typescript-eslint/parser": "^5.48.2",
2224
"autoprefixer": "^10.4.13",
25+
"color2k": "^2.0.1",
2326
"esbuild": "^0.17.1",
2427
"eslint": "^8.32.0",
2528
"eslint-config-prettier": "^8.6.0",
@@ -38,4 +41,3 @@
3841
},
3942
"type": "module"
4043
}
41-

html/pnpm-lock.yaml

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

html/src/app.pcss

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,16 @@
66
html, body { @apply h-full overflow-hidden; }
77

88

9+
html:root {
10+
--read-accesses: 0 72 255;
11+
--write-accesses: 255 113 0;
12+
--all-accesses: 61 9 218;
13+
}
14+
15+
.high-contrast-stroke {
16+
-webkit-text-stroke: medium black;
17+
}
18+
19+
.high-contrast-text-shadow {
20+
text-shadow: 0px 0px 1px black;
21+
}

html/src/components/Layout.svelte

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
import '@skeletonlabs/skeleton/themes/theme-skeleton.css';
33
import '@skeletonlabs/skeleton/styles/all.css';
44
import '../app.pcss';
5-
import { AppShell, AppBar, Drawer } from '@skeletonlabs/skeleton';
5+
import { AppShell, AppBar, Drawer, tooltip } from '@skeletonlabs/skeleton';
6+
import Icon from '@iconify/svelte';
7+
import baselineLightbulb from '@iconify/icons-ic/baseline-lightbulb';
8+
import outlineSplitscreen from '@iconify/icons-ic/outline-splitscreen';
9+
import outlineRectangle from '@iconify/icons-ic/outline-rectangle';
10+
import { pageState, drawerState } from '../lib/stores';
611
</script>
712

813
<!-- App Shell -->
@@ -12,9 +17,38 @@
1217
<AppBar>
1318
<svelte:fragment slot="lead">
1419
<strong class="text-xl uppercase">Memory Visualization</strong>
20+
<strong class="px-3">v1.0.0</strong>
1521
</svelte:fragment>
1622
<svelte:fragment slot="trail">
17-
<strong>v1.0.0</strong>
23+
<div
24+
class="cursor-pointer"
25+
on:click={() => ($drawerState.showSingleAccessTable = !$drawerState.showSingleAccessTable)}
26+
use:tooltip={{
27+
content: 'Toggle between showing read and write separately and showing the total access count',
28+
position: 'bottom'
29+
}}
30+
>
31+
<Icon
32+
class="drop-shadow-xl"
33+
height="32"
34+
icon={$drawerState.showSingleAccessTable ? outlineSplitscreen : outlineRectangle}
35+
width="32"
36+
/>
37+
</div>
38+
<div
39+
class="cursor-pointer"
40+
on:click={() => ($pageState.backGroundContrastBlack = !$pageState.backGroundContrastBlack)}
41+
use:tooltip={{ content: 'Toggle between light and dark background for the memory grid', position: 'bottom' }}
42+
>
43+
<Icon
44+
class="drop-shadow-xl"
45+
color={$pageState.backGroundContrastBlack ? 'black' : 'white'}
46+
height="32"
47+
icon={baselineLightbulb}
48+
width="32"
49+
/>
50+
</div>
51+
<button class="btn btn-ghost btn-sm">About</button>
1852
</svelte:fragment>
1953
</AppBar>
2054
</svelte:fragment>

html/src/components/MemoryRegionBlock.svelte

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { drawerState } from '../lib/stores';
33
import { MemoryRegionManager } from '../lib/types';
44
import { drawerStore } from '@skeletonlabs/skeleton';
5+
import { pageState } from '../lib/stores';
56
67
export let MemoryRegion: MemoryRegionManager;
78
export let index: number;
@@ -11,23 +12,37 @@
1112
let writeCount = 0;
1213
let totalCount = 0;
1314
15+
let readOpacity = 0;
16+
let writeOpacity = 0;
17+
let totalOpacity = 0;
18+
1419
$: {
1520
readCount = MemoryRegion.getReadAccesses(index).length;
1621
writeCount = MemoryRegion.getWriteAccesses(index).length;
1722
totalCount = readCount + writeCount;
1823
24+
// If the maximum is 0, we are dividing by 0, so we set the opacity to 0 in the case of NaN
25+
readOpacity = readCount / MemoryRegion.highestReadCount || 0;
26+
writeOpacity = writeCount / MemoryRegion.highestWriteCount || 0;
27+
totalOpacity = totalCount / MemoryRegion.highestTotalCount || 0;
28+
1929
originalMemoryAddress = MemoryRegion.convertIndexToAddressString(index);
2030
}
2131
</script>
2232

23-
<div class="flex bg-cyan-700 m-0 w-56">
24-
<div class="bg-cyan-400 p-4 flex-1">
33+
<div
34+
class="flex m-0"
35+
class:bg-black={$pageState.backGroundContrastBlack}
36+
class:bg-white={!$pageState.backGroundContrastBlack}
37+
>
38+
<div class="py-1 flex-1 m-auto high-contrast-stroke font-black">
2539
{index}
2640
</div>
27-
<div class="flex flex-col flex-1 bg-cyan-800">
41+
<div class="flex flex-col flex-1" class:text-black={!$pageState.backGroundContrastBlack}>
2842
{#if $drawerState.showSingleAccessTable}
2943
<div
30-
class="flex-1 bg-cyan-600"
44+
class="flex-1 flex justify-center items-center bg-access-all high-contrast-text-shadow"
45+
style="--tw-bg-opacity: {totalOpacity}"
3146
on:click={() => {
3247
drawerStore.open({
3348
position: 'bottom'
@@ -37,11 +52,12 @@
3752
$drawerState.currentMemoryRegionIndex = index;
3853
}}
3954
>
40-
{totalCount}
55+
<div>{totalCount}</div>
4156
</div>
4257
{:else}
4358
<div
44-
class="flex-1 bg-cyan-600"
59+
class="flex-1 bg-access-read high-contrast-text-shadow"
60+
style="--tw-bg-opacity: {readOpacity}"
4561
on:click={() => {
4662
drawerStore.open({
4763
position: 'bottom'
@@ -55,7 +71,8 @@
5571
{readCount}
5672
</div>
5773
<div
58-
class="flex-1 bg-orange-700"
74+
class="flex-1 bg-access-write high-contrast-text-shadow"
75+
style="--tw-bg-opacity: {writeOpacity}"
5976
on:click={() => {
6077
drawerStore.open({
6178
position: 'bottom'

html/src/lib/stores.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export interface DrawerState {
1010
showReadAccess: boolean;
1111
}
1212

13+
export interface PageState {
14+
backGroundContrastBlack: boolean;
15+
}
16+
1317
function createDrawerStateStore() {
1418
const { subscribe, set, update } = writable<DrawerState>({
1519
currentMemoryRegion: null,
@@ -31,16 +35,13 @@ function createDrawerStateStore() {
3135
return currentData.currentMemoryRegion.getAllAccesses(currentData.currentMemoryRegionIndex);
3236
}
3337
if (currentData.showReadAccess) {
34-
return currentData.currentMemoryRegion.getReadAccesses(
35-
currentData.currentMemoryRegionIndex
36-
);
38+
return currentData.currentMemoryRegion.getReadAccesses(currentData.currentMemoryRegionIndex);
3739
} else {
38-
return currentData.currentMemoryRegion.getWriteAccesses(
39-
currentData.currentMemoryRegionIndex
40-
);
40+
return currentData.currentMemoryRegion.getWriteAccesses(currentData.currentMemoryRegionIndex);
4141
}
4242
}
4343
};
4444
}
4545

4646
export const drawerState = createDrawerStateStore();
47+
export const pageState = writable<PageState>({ backGroundContrastBlack: true });

html/src/lib/types.ts

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,14 @@ export class AccessInstance {
5757

5858
this.threadID = {
5959
x: this.threadIdGlobal % kernelParameters.GridDimensions.x,
60-
y:
61-
Math.floor(this.threadIdGlobal / kernelParameters.GridDimensions.x) %
62-
kernelParameters.GridDimensions.y,
63-
z: Math.floor(
64-
this.threadIdGlobal /
65-
(kernelParameters.GridDimensions.x * kernelParameters.GridDimensions.y)
66-
)
60+
y: Math.floor(this.threadIdGlobal / kernelParameters.GridDimensions.x) % kernelParameters.GridDimensions.y,
61+
z: Math.floor(this.threadIdGlobal / (kernelParameters.GridDimensions.x * kernelParameters.GridDimensions.y))
6762
};
6863

6964
this.blockID = {
7065
x: this.blockIdGlobal % kernelParameters.GridDimensions.x,
71-
y:
72-
Math.floor(this.blockIdGlobal / kernelParameters.GridDimensions.x) %
73-
kernelParameters.GridDimensions.y,
74-
z: Math.floor(
75-
this.blockIdGlobal / (kernelParameters.GridDimensions.x * kernelParameters.GridDimensions.y)
76-
)
66+
y: Math.floor(this.blockIdGlobal / kernelParameters.GridDimensions.x) % kernelParameters.GridDimensions.y,
67+
z: Math.floor(this.blockIdGlobal / (kernelParameters.GridDimensions.x * kernelParameters.GridDimensions.y))
7768
};
7869

7970
this.kernelParameters = kernelParameters;
@@ -114,8 +105,22 @@ export class MemoryRegionManager {
114105
private highestIndex: number = Number.MIN_SAFE_INTEGER;
115106

116107
// Store the maximum number of accesses in a single index to later represent it in a heatmap
117-
private highestReadCount = 0;
118-
private highestWriteCount = 0;
108+
private _highestReadCount = 0;
109+
private _highestWriteCount = 0;
110+
private _highestTotalCount = 0;
111+
112+
// For ease of use to not use a method we are providing a getter for the highest counts
113+
get highestReadCount() {
114+
return this._highestReadCount;
115+
}
116+
117+
get highestWriteCount() {
118+
return this._highestWriteCount;
119+
}
120+
121+
get highestTotalCount() {
122+
return this._highestTotalCount;
123+
}
119124

120125
// For 1d arrays, we can display a sparse representation which only shows accessed addresses and not the entire memory space
121126
// if it is a normal number, it is the valid index of the array, if it is a tuple of numbers, this represents the empty spaces between memory accesses
@@ -172,8 +177,8 @@ export class MemoryRegionManager {
172177
this.readAccesses.get(access.index)?.push(access);
173178

174179
// Check if the number of accesses at this index for reading is the highest so far
175-
if (this.readAccesses.get(access.index)?.length > this.highestReadCount) {
176-
this.highestReadCount = this.readAccesses.get(access.index)?.length || 0;
180+
if (this.readAccesses.get(access.index)?.length > this._highestReadCount) {
181+
this._highestReadCount = this.readAccesses.get(access.index)?.length || 0;
177182
}
178183
}
179184

@@ -184,10 +189,17 @@ export class MemoryRegionManager {
184189
this.writeAccesses.get(access.index)?.push(access);
185190

186191
// Check if the number of accesses at this index for writing is the highest so far
187-
if (this.writeAccesses.get(access.index)?.length > this.highestWriteCount) {
188-
this.highestWriteCount = this.writeAccesses.get(access.index)?.length || 0;
192+
if (this.writeAccesses.get(access.index)?.length > this._highestWriteCount) {
193+
this._highestWriteCount = this.writeAccesses.get(access.index)?.length || 0;
189194
}
190195
}
196+
197+
if (this._highestReadCount > this._highestTotalCount) {
198+
this._highestTotalCount = this._highestReadCount;
199+
}
200+
if (this._highestWriteCount > this._highestTotalCount) {
201+
this._highestTotalCount = this._highestWriteCount;
202+
}
191203
}
192204

193205
addMemoryAccessIfInRegion(access: AccessInstance) {

html/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import App from './App.svelte';
22

33
const app = new App({
4-
target: document.getElementById('app')
4+
target: document.body
55
});
66

77
export default app;

0 commit comments

Comments
 (0)