diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 2b4cfe2e..4cc49b70 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -21,6 +21,7 @@ import { SDFVTooltipFunc, SimpleRect, checkCompatSave, + parse_sdfg, stringify_sdfg, } from '../index'; import { SMLayouter } from '../layouter/state_machine/sm_layouter'; @@ -298,19 +299,19 @@ export class SDFGRenderer extends EventEmitter { this.init_elements(); - this.setSDFG(this.sdfg, false); - - this.on('collapse_state_changed', () => { - this.emit('graph_edited'); - }); - this.on('element_position_changed', () => { - this.emit('graph_edited'); - }); - this.on('selection_changed', () => { - this.on_selection_changed(); - }); - this.on('graph_edited', () => { - this.draw_async(); + this.setSDFG(this.sdfg, false).then(() => { + this.on('collapse_state_changed', () => { + this.emit('graph_edited'); + }); + this.on('element_position_changed', () => { + this.emit('graph_edited'); + }); + this.on('selection_changed', () => { + this.on_selection_changed(); + }); + this.on('graph_edited', () => { + this.draw_async(); + }); }); SDFVSettings.getInstance().on('setting_changed', (setting) => { @@ -1218,32 +1219,40 @@ export class SDFGRenderer extends EventEmitter { ); } - public setSDFG(new_sdfg: JsonSDFG, layout: boolean = true): void { - this.sdfg = new_sdfg; + public async setSDFG( + new_sdfg: JsonSDFG, layout: boolean = true + ): Promise { + return new Promise((resolve)=> { + this.sdfg = new_sdfg; - // Update info box - if (this.selected_elements.length === 1) { - const uuid = getGraphElementUUID(this.selected_elements[0]); - if (this.graph) { - this.sdfv_instance?.linkedUI.showElementInfo( - findGraphElementByUUID(this.cfgList, uuid), this - ); + // Update info box + if (this.selected_elements.length === 1) { + const uuid = getGraphElementUUID(this.selected_elements[0]); + if (this.graph) { + this.sdfv_instance?.linkedUI.showElementInfo( + findGraphElementByUUID(this.cfgList, uuid), this + ); + } } - } - if (layout) { - this.updateCFGList(); + if (layout) { + this.updateCFGList(); - this.add_loading_animation(); - setTimeout(() => { - this.relayout(); - this.draw_async(); - }, 10); - } + this.add_loading_animation(); + setTimeout(() => { + this.relayout(); + this.draw_async(); + resolve(); + }, 1); + } - this.all_memlet_trees_sdfg = memletTreeComplete(this.sdfg); + this.all_memlet_trees_sdfg = memletTreeComplete(this.sdfg); - this.update_fast_memlet_lookup(); + this.update_fast_memlet_lookup(); + + if (!layout) + resolve(); + }); } // Set mouse events (e.g., click, drag, zoom) @@ -2857,8 +2866,9 @@ export class SDFGRenderer extends EventEmitter { } } this.deselect(); - this.setSDFG(this.sdfg); - this.emit('graph_edited'); + this.setSDFG(this.sdfg).then(() => { + this.emit('graph_edited'); + }); } // Ctrl + Shift Accelerators temporarily disabled due to a bug with @@ -4101,11 +4111,8 @@ export class SDFGRenderer extends EventEmitter { if (!(this.sdfv_instance instanceof SDFV)) return; - const sdfv = this.sdfv_instance; - if (sdfv instanceof WebSDFV) { - sdfv.setSDFG(this.sdfg); - sdfv.getLocalViewRenderer()?.resizeObserver.disconnect(); - } + if (this.sdfv_instance instanceof WebSDFV) + this.sdfv_instance.setSDFG(this.sdfg); } public async localViewSelection(): Promise { @@ -4114,7 +4121,8 @@ export class SDFGRenderer extends EventEmitter { // Transition to the local view by first cutting out the selection. try { - this.cutoutSelection(true); + const origSdfg = stringify_sdfg(this.sdfg); + await this.cutoutSelection(true); const lRenderer = new LViewRenderer(this.sdfv_instance, this.container); const lGraph = await LViewParser.parseGraph(this.graph, lRenderer); @@ -4134,6 +4142,7 @@ export class SDFGRenderer extends EventEmitter { exitBtn.style.left = '10px'; exitBtn.title = 'Exit local view'; exitBtn.onclick = () => { + this.sdfg = parse_sdfg(origSdfg); this.exitLocalView(); this.container.removeChild(exitBtn); }; @@ -4152,7 +4161,9 @@ export class SDFGRenderer extends EventEmitter { } } - public cutoutSelection(_suppressSave: boolean = false): void { + public async cutoutSelection( + _suppressSave: boolean = false + ): Promise { /* Rule set for creating a cutout subgraph: * Edges are selected according to the subgraph nodes - all edges * between subgraph nodes are preserved. @@ -4276,7 +4287,7 @@ export class SDFGRenderer extends EventEmitter { } // Set root SDFG as the new SDFG - this.setSDFG(rootSDFG as JsonSDFG); + return this.setSDFG(rootSDFG as JsonSDFG); } } diff --git a/src/sdfv.ts b/src/sdfv.ts index 8e4858ce..b2a5e5b3 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -134,6 +134,7 @@ export abstract class SDFV implements ISDFV { public set_renderer(renderer: SDFGRenderer | null): void { if (renderer) { this.localViewRenderer?.destroy(); + this.localViewRenderer?.resizeObserver.disconnect(); this.localViewRenderer = null; } this.renderer = renderer; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index ce5622c5..4ebd7eed 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -161,12 +161,17 @@ function tempColor(badness: number): [number, number, number] { let saturation = 1.0; let lightness = 0.75; try { - saturation = parseFloat( + const rSaturation = parseFloat( SDFGRenderer.getCssProperty('--overlay-color-saturation') ); - lightness = parseFloat( + if (rSaturation !== undefined && !Number.isNaN(rSaturation)) + saturation = rSaturation; + + const rLightness = parseFloat( SDFGRenderer.getCssProperty('--overlay-color-lightness') ); + if (rLightness !== undefined && !Number.isNaN(rLightness)) + lightness = rLightness; } catch (_ignored) { // Ignored. } diff --git a/tests/test_graphs/while_do.sdfg b/tests/test_graphs/while_do.sdfg new file mode 100644 index 00000000..c621599a --- /dev/null +++ b/tests/test_graphs/while_do.sdfg @@ -0,0 +1,503 @@ +{ + "type": "SDFG", + "attributes": { + "arg_names": [ + "A" + ], + "constants_prop": {}, + "_arrays": { + "A": { + "type": "Array", + "attributes": { + "allow_conflicts": false, + "strides": [ + "1" + ], + "total_size": "10", + "offset": [ + "0" + ], + "may_alias": false, + "alignment": 0, + "start_offset": 0, + "optional": false, + "pool": false, + "dtype": "float64", + "shape": [ + "10" + ], + "transient": false, + "storage": "Default", + "lifetime": "Scope", + "location": {}, + "debuginfo": null + } + } + }, + "symbols": { + "i": "int64" + }, + "instrument": "No_Instrumentation", + "global_code": { + "frame": { + "string_data": "", + "language": "CPP" + } + }, + "init_code": { + "frame": { + "string_data": "", + "language": "CPP" + } + }, + "exit_code": { + "frame": { + "string_data": "", + "language": "CPP" + } + }, + "orig_sdfg": null, + "transformation_hist": [], + "logical_groups": [], + "openmp_sections": true, + "debuginfo": { + "type": "DebugInfo", + "start_line": 3, + "end_line": 9, + "start_column": 0, + "end_column": 0, + "filename": "/mnt/d/UserData/Documents/ETH/SPCL/Layouting/CFG/cfgs/while_do.py" + }, + "_pgrids": {}, + "_subarrays": {}, + "_rdistrarrays": {}, + "callback_mapping": {}, + "name": "prog", + "hash": "027eadba419830e893c02c4e9ba4fc044a377cda2a87d19fa45bcf2840195d63" + }, + "nodes": [ + { + "type": "SDFGState", + "label": "while_guard", + "id": 0, + "collapsed": false, + "scope_dict": { + "-1": [] + }, + "nodes": [], + "edges": [], + "attributes": { + "is_collapsed": false, + "nosync": false, + "instrument": "No_Instrumentation", + "symbol_instrument": "No_Instrumentation", + "symbol_instrument_condition": { + "string_data": "1", + "language": "CPP" + }, + "executions": "0", + "dynamic_executions": true, + "ranges": {}, + "location": {} + } + }, + { + "type": "SDFGState", + "label": "assign_7_8", + "id": 1, + "collapsed": false, + "scope_dict": { + "-1": [ + 0, + 1 + ] + }, + "nodes": [ + { + "type": "AccessNode", + "label": "A", + "attributes": { + "setzero": false, + "debuginfo": { + "type": "DebugInfo", + "start_line": 7, + "end_line": 7, + "start_column": 10, + "end_column": 10, + "filename": "/mnt/d/UserData/Documents/ETH/SPCL/Layouting/CFG/cfgs/while_do.py" + }, + "data": "A", + "instrument": "No_Instrumentation", + "instrument_condition": { + "string_data": "1", + "language": "CPP" + }, + "in_connectors": {}, + "out_connectors": {} + }, + "id": 0, + "scope_entry": null, + "scope_exit": null + }, + { + "type": "Tasklet", + "label": "assign_7_8", + "attributes": { + "code": { + "string_data": "__out = 0", + "language": "Python" + }, + "state_fields": [], + "code_global": { + "string_data": "", + "language": "CPP" + }, + "code_init": { + "string_data": "", + "language": "CPP" + }, + "code_exit": { + "string_data": "", + "language": "CPP" + }, + "debuginfo": { + "type": "DebugInfo", + "start_line": 7, + "end_line": 7, + "start_column": 10, + "end_column": 10, + "filename": "/mnt/d/UserData/Documents/ETH/SPCL/Layouting/CFG/cfgs/while_do.py" + }, + "instrument": "No_Instrumentation", + "side_effects": null, + "label": "assign_7_8", + "location": {}, + "environments": [], + "in_connectors": {}, + "out_connectors": { + "__out": null + } + }, + "id": 1, + "scope_entry": null, + "scope_exit": null + } + ], + "edges": [ + { + "type": "MultiConnectorEdge", + "attributes": { + "data": { + "type": "Memlet", + "attributes": { + "volume": "1", + "dynamic": false, + "subset": { + "type": "Range", + "ranges": [ + { + "start": "i", + "end": "i", + "step": "1", + "tile": "1" + } + ] + }, + "other_subset": null, + "data": "A", + "wcr": null, + "debuginfo": null, + "wcr_nonatomic": false, + "allow_oob": false, + "src_subset": null, + "dst_subset": { + "type": "Range", + "ranges": [ + { + "start": "i", + "end": "i", + "step": "1", + "tile": "1" + } + ] + }, + "is_data_src": false, + "num_accesses": "1" + } + } + }, + "src": "1", + "dst": "0", + "dst_connector": null, + "src_connector": "__out" + } + ], + "attributes": { + "is_collapsed": false, + "nosync": false, + "instrument": "No_Instrumentation", + "symbol_instrument": "No_Instrumentation", + "symbol_instrument_condition": { + "string_data": "1", + "language": "CPP" + }, + "executions": "0", + "dynamic_executions": true, + "ranges": {}, + "location": {} + } + }, + { + "type": "SDFGState", + "label": "assign_9_4", + "id": 2, + "collapsed": false, + "scope_dict": { + "-1": [ + 0, + 1 + ] + }, + "nodes": [ + { + "type": "AccessNode", + "label": "A", + "attributes": { + "setzero": false, + "debuginfo": { + "type": "DebugInfo", + "start_line": 9, + "end_line": 9, + "start_column": 6, + "end_column": 6, + "filename": "/mnt/d/UserData/Documents/ETH/SPCL/Layouting/CFG/cfgs/while_do.py" + }, + "data": "A", + "instrument": "No_Instrumentation", + "instrument_condition": { + "string_data": "1", + "language": "CPP" + }, + "in_connectors": {}, + "out_connectors": {} + }, + "id": 0, + "scope_entry": null, + "scope_exit": null + }, + { + "type": "Tasklet", + "label": "assign_9_4", + "attributes": { + "code": { + "string_data": "__out = 1", + "language": "Python" + }, + "state_fields": [], + "code_global": { + "string_data": "", + "language": "CPP" + }, + "code_init": { + "string_data": "", + "language": "CPP" + }, + "code_exit": { + "string_data": "", + "language": "CPP" + }, + "debuginfo": { + "type": "DebugInfo", + "start_line": 9, + "end_line": 9, + "start_column": 6, + "end_column": 6, + "filename": "/mnt/d/UserData/Documents/ETH/SPCL/Layouting/CFG/cfgs/while_do.py" + }, + "instrument": "No_Instrumentation", + "side_effects": null, + "label": "assign_9_4", + "location": {}, + "environments": [], + "in_connectors": {}, + "out_connectors": { + "__out": null + } + }, + "id": 1, + "scope_entry": null, + "scope_exit": null + } + ], + "edges": [ + { + "type": "MultiConnectorEdge", + "attributes": { + "data": { + "type": "Memlet", + "attributes": { + "volume": "1", + "dynamic": false, + "subset": { + "type": "Range", + "ranges": [ + { + "start": "0", + "end": "0", + "step": "1", + "tile": "1" + } + ] + }, + "other_subset": null, + "data": "A", + "wcr": null, + "debuginfo": null, + "wcr_nonatomic": false, + "allow_oob": false, + "src_subset": null, + "dst_subset": { + "type": "Range", + "ranges": [ + { + "start": "0", + "end": "0", + "step": "1", + "tile": "1" + } + ] + }, + "is_data_src": false, + "num_accesses": "1" + } + } + }, + "src": "1", + "dst": "0", + "dst_connector": null, + "src_connector": "__out" + } + ], + "attributes": { + "is_collapsed": false, + "nosync": false, + "instrument": "No_Instrumentation", + "symbol_instrument": "No_Instrumentation", + "symbol_instrument_condition": { + "string_data": "1", + "language": "CPP" + }, + "executions": "1", + "dynamic_executions": false, + "ranges": {}, + "location": {} + } + }, + { + "type": "SDFGState", + "label": "state", + "id": 3, + "collapsed": false, + "scope_dict": { + "-1": [] + }, + "nodes": [], + "edges": [], + "attributes": { + "is_collapsed": false, + "nosync": false, + "instrument": "No_Instrumentation", + "symbol_instrument": "No_Instrumentation", + "symbol_instrument_condition": { + "string_data": "1", + "language": "CPP" + }, + "executions": "0", + "dynamic_executions": true, + "ranges": {}, + "location": {} + } + } + ], + "edges": [ + { + "type": "Edge", + "attributes": { + "data": { + "type": "InterstateEdge", + "attributes": { + "assignments": { + "i": "0" + }, + "condition": { + "string_data": "1", + "language": "Python" + } + }, + "label": "i=0" + } + }, + "src": "3", + "dst": "0" + }, + { + "type": "Edge", + "attributes": { + "data": { + "type": "InterstateEdge", + "attributes": { + "assignments": {}, + "condition": { + "string_data": "(not (i < 10))", + "language": "Python" + } + }, + "label": "(not (i < 10))" + } + }, + "src": "0", + "dst": "2" + }, + { + "type": "Edge", + "attributes": { + "data": { + "type": "InterstateEdge", + "attributes": { + "assignments": {}, + "condition": { + "string_data": "(i < 10)", + "language": "Python" + } + }, + "label": "(i < 10)" + } + }, + "src": "0", + "dst": "1" + }, + { + "type": "Edge", + "attributes": { + "data": { + "type": "InterstateEdge", + "attributes": { + "assignments": { + "i": "(i + 1)" + }, + "condition": { + "string_data": "1", + "language": "Python" + } + }, + "label": "i=(i + 1)" + } + }, + "src": "1", + "dst": "0" + } + ], + "sdfg_list_id": 0, + "start_state": 0, + "dace_version": "0.14.2" +} \ No newline at end of file diff --git a/tests/unit/layouter/graphlib/algorithms/cycles.test.ts b/tests/unit/layouter/graphlib/algorithms/cycles.test.ts index c3b8bcf2..06faa5e1 100644 --- a/tests/unit/layouter/graphlib/algorithms/cycles.test.ts +++ b/tests/unit/layouter/graphlib/algorithms/cycles.test.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { allBackedges, simpleCycles, diff --git a/tests/unit/layouter/graphlib/di_graph.test.ts b/tests/unit/layouter/graphlib/di_graph.test.ts index d7181147..ad2fd05a 100644 --- a/tests/unit/layouter/graphlib/di_graph.test.ts +++ b/tests/unit/layouter/graphlib/di_graph.test.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { DiGraph } from '../../../../src/layouter/graphlib/di_graph'; function testAddEdges(): void { diff --git a/tests/unit/layouter/graphlib/graph.test.ts b/tests/unit/layouter/graphlib/graph.test.ts index fe8566c7..555380ee 100644 --- a/tests/unit/layouter/graphlib/graph.test.ts +++ b/tests/unit/layouter/graphlib/graph.test.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { Graph } from '../../../../src/layouter/graphlib/graph'; function testInsertNode(): void { diff --git a/tests/unit/layouter/state_machine/sm_layouter.test.ts b/tests/unit/layouter/state_machine/sm_layouter.test.ts index 37380ba9..978fbc69 100644 --- a/tests/unit/layouter/state_machine/sm_layouter.test.ts +++ b/tests/unit/layouter/state_machine/sm_layouter.test.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { DiGraph } from '../../../../src/layouter/graphlib/di_graph'; import { BACKEDGE_SPACING, @@ -304,6 +306,50 @@ function testSkipLoopWithBreakReturn(): void { expect(graph.get('7')?.rank).toBe(7); } +function testMultiEntryExit(): void { + const graph = new DiGraph(); + + // Construct graph. + // 0 1 + // | | + // 2--| + // | + // 3 + + constructEdge(graph, '0', '2'); + constructEdge(graph, '1', '2'); + constructEdge(graph, '2', '3'); + + const layouter = new SMLayouter(graph); + layouter.doLayout(); + + expect(graph.get('0')?.rank).toBe(1); + expect(graph.get('1')?.rank).toBe(1); + expect(graph.get('2')?.rank).toBe(2); + expect(graph.get('3')?.rank).toBe(3); + + const graph2 = new DiGraph(); + + // Construct graph. + // 0 + // | + // 1--| + // | | + // 2 3 + + constructEdge(graph2, '0', '1'); + constructEdge(graph2, '1', '2'); + constructEdge(graph2, '1', '3'); + + const layouter2 = new SMLayouter(graph2); + layouter2.doLayout(); + + expect(graph2.get('0')?.rank).toBe(0); + expect(graph2.get('1')?.rank).toBe(1); + expect(graph2.get('2')?.rank).toBe(2); + expect(graph2.get('3')?.rank).toBe(2); +} + describe('Test vertical state machine layout ranking', () => { test('Basic branching', testBasicBranching); test('Nested branching', testNestedBranching); @@ -320,6 +366,7 @@ describe('Test vertical state machine layout ranking', () => { 'Test conditionally skipped loop with break and returns', testSkipLoopWithBreakReturn ); + test('Test multiple source nodes and sink nodes', testMultiEntryExit); }); function testEdgeRoutingSelfLoop(): void { diff --git a/tests/unit/sdfg_diff_viewer.test.ts b/tests/unit/sdfg_diff_viewer.test.ts index bb04dd74..f8fbdcec 100644 --- a/tests/unit/sdfg_diff_viewer.test.ts +++ b/tests/unit/sdfg_diff_viewer.test.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import path from 'path'; import fs from 'fs'; import { diff --git a/tests/unit/utils/collections.test.ts b/tests/unit/utils/collections.test.ts new file mode 100644 index 00000000..20463216 --- /dev/null +++ b/tests/unit/utils/collections.test.ts @@ -0,0 +1,82 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + +import { AccessStack, LinkedStack } from '../../../src/utils/collections'; + +function testLinkedStackConstruction(): void { + const lStack = new LinkedStack(); + expect(lStack.size).toBe(0); + expect(lStack.top).toBeUndefined(); + expect(lStack.pop()).toBeUndefined(); +} + +function testLinkedStackInsertion(): void { + const lStack = new LinkedStack(); + + lStack.push(0); + lStack.push(1); + lStack.push(2); + const rVal = lStack.push(3); + + expect(lStack.size).toBe(4); + expect(lStack.top?.value).toBe(3); + expect(rVal).toBe(4); +} + +function testLinkedStackPop(): void { + const lStack = new LinkedStack(); + + lStack.push(0); + lStack.push(1); + lStack.push(2); + lStack.push(3); + + const rval = lStack.pop(); + + expect(lStack.size).toBe(3); + expect(lStack.top?.value).toBe(2); + expect(rval).toBe(3); +} + +describe('Test linked stack data structure', () => { + test('Construction', testLinkedStackConstruction); + test('Insertion', testLinkedStackInsertion); + test('Popping', testLinkedStackPop); +}); + +function testAccessStackConstruction(): void { + const aStack = new AccessStack(); + expect(aStack.size).toBe(0); + expect(aStack.top).toBeUndefined(); + expect(aStack.pop()).toBeUndefined(); +} + +function testAccessStackTouching(): void { + const aStack = new AccessStack(); + + aStack.push(0); + aStack.push(1); + aStack.push(2); + aStack.push(3); + aStack.push(4); + aStack.push(5); + const rval = aStack.pop(); + + expect(aStack.size).toBe(5); + expect(aStack.top?.value).toBe(4); + expect(rval).toBe(5); + + expect(aStack.touch(0)).toBe(4); + expect(aStack.touch(0)).toBe(0); + expect(aStack.top?.value).toBe(0); + expect(aStack.touch(2)).toBe(3); + expect(aStack.touch(2)).toBe(0); + expect(aStack.top?.value).toBe(2); + expect(aStack.touch(5)).toBe(-1); + expect(aStack.top?.value).toBe(5); + expect(aStack.size).toBe(6); +} + +describe('Test Access Stack data structure', () => { + test('Construction', testAccessStackConstruction); + test('Touching', testAccessStackTouching); +}); diff --git a/tests/unit/utils/sdfg/dotgraph.test.ts b/tests/unit/utils/sdfg/dotgraph.test.ts new file mode 100644 index 00000000..339dcd8f --- /dev/null +++ b/tests/unit/utils/sdfg/dotgraph.test.ts @@ -0,0 +1,42 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + +import path from 'path'; +import fs from 'fs'; +import { checkCompatLoad, JsonSDFG, parse_sdfg } from '../../../../src'; +import { cfgToDotGraph } from '../../../../src/utils/sdfg/dotgraph'; + +function _loadSDFG(name: string): JsonSDFG { + const file = path.join( + __dirname, '..', '..', '..', 'test_graphs', name + '.sdfg' + ); + const contents = fs.readFileSync(file, { + encoding: 'utf-8', + }); + return checkCompatLoad(parse_sdfg(contents)); +} + +function testWhileDoToDot(): void { + const sdfg = _loadSDFG('while_do'); + const dotString = cfgToDotGraph(sdfg); + + expect(dotString).toContain('state -> while_guard'); + expect(dotString).toContain('while_guard -> assign_7_8'); + expect(dotString).toContain('while_guard -> assign_9_4'); + expect(dotString).toContain('assign_7_8 -> while_guard'); + expect(dotString).not.toContain('state -> state'); + expect(dotString).not.toContain('state -> assign_7_8'); + expect(dotString).not.toContain('state -> assign_9_4'); + expect(dotString).not.toContain('while_guard -> state'); + expect(dotString).not.toContain('while_guard -> while_guard'); + expect(dotString).not.toContain('assign_7_8 -> assign_7_8'); + expect(dotString).not.toContain('assign_7_8 -> assign_9_4'); + expect(dotString).not.toContain('assign_7_8 -> state'); + expect(dotString).not.toContain('assign_9_4 -> assign_7_8'); + expect(dotString).not.toContain('assign_9_4 -> state'); + expect(dotString).not.toContain('assign_9_4 -> while_guard'); + expect(dotString).not.toContain('assign_9_4 -> assign_9_4'); +} + +describe('Test SDFG to DOT graph conversion', () => { + test('While-Do loop', testWhileDoToDot); +}); diff --git a/tests/unit/utils/sdfg/memlet_trees.test.ts b/tests/unit/utils/sdfg/memlet_trees.test.ts new file mode 100644 index 00000000..3f53434b --- /dev/null +++ b/tests/unit/utils/sdfg/memlet_trees.test.ts @@ -0,0 +1,30 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + +import path from 'path'; +import fs from 'fs'; +import { checkCompatLoad, JsonSDFG, parse_sdfg } from '../../../../src'; +import { memletTreeComplete } from '../../../../src/utils/sdfg/memlet_trees'; + +function _loadSDFG(name: string): JsonSDFG { + const file = path.join( + __dirname, '..', '..', '..', 'test_graphs', name + '.sdfg' + ); + const contents = fs.readFileSync(file, { + encoding: 'utf-8', + }); + return checkCompatLoad(parse_sdfg(contents)); +} + +function testMemletTreeNestedSDFGMultiMap(): void { + const sdfg = _loadSDFG('gemm_expanded_pure_tiled'); + const mtree = memletTreeComplete(sdfg); + + expect(mtree.length).toBe(3); + expect(mtree[0].size).toBe(6); + expect(mtree[1].size).toBe(6); + expect(mtree[2].size).toBe(6); +} + +describe('Test memlet tree construction', () => { + test('Nested SDFG with nested maps', testMemletTreeNestedSDFGMultiMap); +}); diff --git a/tests/unit/utils/sdfg/sdfg_utils.test.ts b/tests/unit/utils/sdfg/sdfg_utils.test.ts index 9584e6bb..b99cf97e 100644 --- a/tests/unit/utils/sdfg/sdfg_utils.test.ts +++ b/tests/unit/utils/sdfg/sdfg_utils.test.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import path from 'path'; import fs from 'fs'; import { diff --git a/tests/unit/utils/utils.test.ts b/tests/unit/utils/utils.test.ts new file mode 100644 index 00000000..22c5aeeb --- /dev/null +++ b/tests/unit/utils/utils.test.ts @@ -0,0 +1,13 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + +import { getTempColorHslString } from '../../../src'; + +function testTempColor(): void { + expect(getTempColorHslString(1.0)).toBe('hsl(0,100%,75%)'); + expect(getTempColorHslString(0.0)).toBe('hsl(120,100%,75%)'); + expect(getTempColorHslString(0.5)).toBe('hsl(60,100%,75%)'); +} + +describe('Test utility functions', () => { + test('Badness to temperature color conversion', testTempColor); +});