const assert = require('assert'); const helpers = require('../frontend/canvas-helpers.js'); const handles = helpers.buildPortHandles({ a0: { x: 0, y: 0, a: 180 }, b0: { x: 0, y: 0, a: 0 }, a1: { x: -91.7, y: 4.475, a: 180 }, a2: { x: -91.7, y: -4.475, a: 180 }, b1: { x: 91.7, y: 4.475, a: 0 }, b2: { x: 91.7, y: -4.475, a: 0 }, ep2a: { x: -37.8, y: -20, a: 270 }, ep2b: { x: -37.8, y: 20, a: 90 }, }); assert.deepStrictEqual(handles.map(handle => handle.name), ['a1', 'a2', 'b1', 'b2', 'ep2b', 'ep2a']); assert.deepStrictEqual(handles.filter(handle => handle.position === 'left').map(handle => handle.name), ['a1', 'a2']); assert.deepStrictEqual(handles.filter(handle => handle.position === 'right').map(handle => handle.name), ['b1', 'b2']); assert.deepStrictEqual(handles.find(handle => handle.name === 'ep2b').position, 'top'); assert.deepStrictEqual(handles.find(handle => handle.name === 'ep2a').position, 'bottom'); assert.strictEqual(handles.find(handle => handle.name === 'a1').style.top, '15%'); assert.strictEqual(handles.find(handle => handle.name === 'a2').style.top, '85%'); assert.strictEqual(handles.find(handle => handle.name === 'ep2b').style.left, '50%'); const args = helpers.createForgeArguments(); assert(Object.keys(args).length >= 10); assert.strictEqual(helpers.isForgeComponent('generate with mxpic_forge'), true); const yaml = helpers.buildInstanceYaml({ instanceName: 'component_1', componentName: 'generate with mxpic_forge', componentPath: 'ignored/path', position: { x: 12.34, y: -5 }, rotation: 90, forgeArguments: { function_name: 'mmi1x2', length: 25.5, include_heater: true } }); assert(yaml.includes('component: generate_with_forge')); assert(yaml.includes('function_name: "mmi1x2"')); assert(yaml.includes('length: 25.5')); assert(yaml.includes('include_heater: true')); const projectInstancesYaml = helpers.buildInstancesYaml({ nodes: [ { id: 'node-1', type: 'rotatableNode', position: { x: 10, y: 20 }, data: { componentDisplayName: 'component_1', componentName: 'PDK_A', rotation: 0 } }, { id: 'node-2', type: 'rotatableNode', position: { x: 30, y: 40 }, data: { componentDisplayName: 'cell_1', componentName: 'canvas_1', type: 'composite', rotation: 90 } } ], resolveComponentPath: name => name === 'PDK_A' ? 'foundry/path/PDK_A' : name }); assert(projectInstancesYaml.includes('component_1:')); assert(projectInstancesYaml.includes('component: foundry/path/PDK_A')); assert(projectInstancesYaml.includes('cell_1:')); assert(projectInstancesYaml.includes('component: canvas_1')); const pagePortsYaml = helpers.buildPortsYaml({ x: 50, y: 150, a: 90 }); assert(pagePortsYaml.includes('- name: port')); assert(pagePortsYaml.includes('x: 50.0')); assert(pagePortsYaml.includes('y: 150.0')); assert(pagePortsYaml.includes('angle: 90.0')); const componentPorts = helpers.buildPageComponentPorts({ x: 12, y: -6, a: 180 }); assert.deepStrictEqual(componentPorts, { port: { x: 12, y: -6, a: 180, width: 0.5 } }); const elementNodes = [ { id: 'port-1', type: 'portNode', position: { x: 10, y: 20 }, data: { componentDisplayName: 'in0', elementType: 'port', angle: 180, width: 0.7, layer: 'WG_CORE', description: 'input port' } }, { id: 'anchor-1', type: 'rotatableNode', position: { x: 30, y: 40 }, data: { componentDisplayName: 'anchor_1', componentName: 'Anchor', elementType: 'anchor', rotation: 0 } }, { id: 'mmi-1', type: 'rotatableNode', position: { x: 50, y: 60 }, data: { componentDisplayName: 'component_1', componentName: 'MMI', rotation: 0 } } ]; assert.deepStrictEqual(helpers.buildElementPorts('port', { angle: 90, width: 0.8 }), { port: { x: 0, y: 0, a: 90, width: 0.8 } }); assert.deepStrictEqual(Object.keys(helpers.buildElementPorts('anchor')), ['left', 'right']); const canvasPortsYaml = helpers.buildCanvasPortsYaml(elementNodes); assert(canvasPortsYaml.includes('name: in0')); assert(canvasPortsYaml.includes('description: "input port"')); assert(canvasPortsYaml.includes('width: 0.7')); const elementsYaml = helpers.buildElementsYaml(elementNodes); assert(elementsYaml.includes('in0:')); assert(elementsYaml.includes('type: port')); assert(elementsYaml.includes('anchor_1:')); assert(elementsYaml.includes('type: anchor')); const instancesWithoutElements = helpers.buildInstancesYaml({ nodes: elementNodes, resolveComponentPath: name => name }); assert(!instancesWithoutElements.includes('anchor_1:')); assert(!instancesWithoutElements.includes('in0:')); assert(instancesWithoutElements.includes('component_1:')); const multiPortComponentPorts = helpers.buildPageComponentPorts(null, elementNodes); assert.deepStrictEqual(multiPortComponentPorts.in0, { x: 10, y: 20, a: 180, width: 0.7 }); const technologyManifest = { defaults: { xsection: 'strip', width: 0.45, radius: 10, routing_type: 'euler_bend' }, xsections: { strip: { family: 'optical', default_width: 0.45 }, rib_low: { family: 'optical', default_width: 0.5 }, metal_1: { family: 'electrical', default_width: 5 }, metal_2: { family: 'electrical', default_width: 6 } }, routing_types: ['euler_bend', 'standard_bend'] }; const routeDefaults = helpers.createRouteSettings(technologyManifest); assert.deepStrictEqual(routeDefaults, { xsection: 'strip', family: 'optical', width: 0.45, radius: 10, routing_type: 'euler_bend', widthEdited: false }); const metalRoute = helpers.updateRouteXsection(routeDefaults, 'metal_1', technologyManifest); assert.strictEqual(metalRoute.family, 'electrical'); assert.strictEqual(metalRoute.width, 5); const manuallyEditedWidth = helpers.updateRouteField(routeDefaults, 'width', 0.62, technologyManifest); const changedXsection = helpers.updateRouteXsection(manuallyEditedWidth, 'rib_low', technologyManifest); assert.strictEqual(changedXsection.width, 0.62); assert.strictEqual(changedXsection.family, 'optical'); const styledStrip = helpers.routeStyleForSettings({ xsection: 'strip', family: 'optical' }, false); const styledMetal = helpers.routeStyleForSettings({ xsection: 'metal_1', family: 'electrical' }, true); assert.notStrictEqual(styledStrip.style.stroke, styledMetal.style.stroke); assert(styledMetal.style.strokeDasharray, 'electrical routes should use a visibly different line treatment'); assert(styledMetal.style.strokeWidth > styledStrip.style.strokeWidth); const routeYaml = helpers.buildBundlesYaml({ nodes: [ { id: 'a', data: { componentDisplayName: 'inst_a' } }, { id: 'b', data: { componentDisplayName: 'inst_b' } } ], edges: [{ id: 'edge-a-b', source: 'a', target: 'b', sourceHandle: 'out', targetHandle: 'in', data: { route: { xsection: 'metal_1', family: 'electrical', width: 5, radius: 20, routing_type: 'standard_bend' } } }] }, technologyManifest); assert(routeYaml.includes('xsection: metal_1')); assert(routeYaml.includes('family: electrical')); assert(routeYaml.includes('radius: 20')); assert(routeYaml.includes('routing_type: standard_bend')); const edgeA = { id: 'edge-a-b', source: 'a', target: 'b', data: { route: { family: 'optical' } } }; const edgeB = { id: 'edge-c-d', source: 'c', target: 'd', data: { route: { family: 'optical' } } }; const edgeC = { id: 'edge-e-f', source: 'e', target: 'f', data: { route: { family: 'electrical' } } }; const crossingNodes = { a: { position: { x: 0, y: 0 } }, b: { position: { x: 100, y: 100 } }, c: { position: { x: 0, y: 100 } }, d: { position: { x: 100, y: 0 } }, e: { position: { x: 0, y: 100 } }, f: { position: { x: 100, y: 0 } } }; assert.strictEqual(helpers.findSameFamilyRouteCrossing(edgeB, [edgeA], crossingNodes).conflictEdge.id, 'edge-a-b'); assert.strictEqual(helpers.findSameFamilyRouteCrossing(edgeC, [edgeA], crossingNodes), null);