Internally, netlistsvg generates a JSON object very similar to the ELK JSON used by this project. For example, using one of the Fomu blink examples, this is generated by netlistsvg:
And this is the corresponding ELK JSON before being handed off to ELK for rendering into an SVG:
Details
{
"id": "Fomu_Blink",
"children": [
{
"id": "clk_generator",
"width": 30,
"height": 20,
"ports": [
{
"id": "clk_generator.clk",
"width": 1,
"height": 1,
"x": 0,
"y": 10,
"labels": [
{
"id": "clk_generator.clk.label",
"text": "clk",
"x": -13,
"y": -10,
"width": 18,
"height": 11
}
]
},
{
"id": "clk_generator.cnt",
"width": 1,
"height": 1,
"x": 30,
"y": 10,
"labels": [
{
"id": "clk_generator.cnt.label",
"text": "cnt",
"x": -5,
"y": -10,
"width": 18,
"height": 11
}
]
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "clk_generator.label.ref",
"text": "clk_generator",
"x": "15",
"y": -10,
"height": 11,
"width": 78
}
]
},
{
"id": "rgba_driver",
"width": 30,
"height": 100,
"ports": [
{
"id": "rgba_driver.CURREN",
"width": 1,
"height": 1,
"x": 0,
"y": 10,
"labels": [
{
"id": "rgba_driver.CURREN.label",
"text": "CURREN",
"x": -13,
"y": -10,
"width": 36,
"height": 11
}
]
},
{
"id": "rgba_driver.RGB0PWM",
"width": 1,
"height": 1,
"x": 0,
"y": 30,
"labels": [
{
"id": "rgba_driver.RGB0PWM.label",
"text": "RGB0PWM",
"x": -13,
"y": -10,
"width": 42,
"height": 11
}
]
},
{
"id": "rgba_driver.RGB1PWM",
"width": 1,
"height": 1,
"x": 0,
"y": 50,
"labels": [
{
"id": "rgba_driver.RGB1PWM.label",
"text": "RGB1PWM",
"x": -13,
"y": -10,
"width": 42,
"height": 11
}
]
},
{
"id": "rgba_driver.RGB2PWM",
"width": 1,
"height": 1,
"x": 0,
"y": 70,
"labels": [
{
"id": "rgba_driver.RGB2PWM.label",
"text": "RGB2PWM",
"x": -13,
"y": -10,
"width": 42,
"height": 11
}
]
},
{
"id": "rgba_driver.RGBLEDEN",
"width": 1,
"height": 1,
"x": 0,
"y": 90,
"labels": [
{
"id": "rgba_driver.RGBLEDEN.label",
"text": "RGBLEDEN",
"x": -13,
"y": -10,
"width": 48,
"height": 11
}
]
},
{
"id": "rgba_driver.RGB0",
"width": 1,
"height": 1,
"x": 30,
"y": 10,
"labels": [
{
"id": "rgba_driver.RGB0.label",
"text": "RGB0",
"x": -5,
"y": -10,
"width": 24,
"height": 11
}
]
},
{
"id": "rgba_driver.RGB1",
"width": 1,
"height": 1,
"x": 30,
"y": 30,
"labels": [
{
"id": "rgba_driver.RGB1.label",
"text": "RGB1",
"x": -5,
"y": -10,
"width": 24,
"height": 11
}
]
},
{
"id": "rgba_driver.RGB2",
"width": 1,
"height": 1,
"x": 30,
"y": 50,
"labels": [
{
"id": "rgba_driver.RGB2.label",
"text": "RGB2",
"x": -5,
"y": -10,
"width": 24,
"height": 11
}
]
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "rgba_driver.label.ref",
"text": "rgba_driver",
"x": "15",
"y": -10,
"height": 11,
"width": 66
}
]
},
{
"id": "clki",
"width": 30,
"height": 20,
"ports": [
{
"id": "clki.Y",
"width": 0,
"height": 0,
"x": 30,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "clki.label.ref",
"text": "clki",
"x": "15",
"y": -10,
"height": 11,
"width": 24
}
]
},
{
"id": "rgb0",
"width": 30,
"height": 20,
"ports": [
{
"id": "rgb0.A",
"width": 0,
"height": 0,
"x": 0,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "rgb0.label.ref",
"text": "rgb0",
"x": "15",
"y": -10,
"height": 11,
"width": 24
}
]
},
{
"id": "rgb1",
"width": 30,
"height": 20,
"ports": [
{
"id": "rgb1.A",
"width": 0,
"height": 0,
"x": 0,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "rgb1.label.ref",
"text": "rgb1",
"x": "15",
"y": -10,
"height": 11,
"width": 24
}
]
},
{
"id": "rgb2",
"width": 30,
"height": 20,
"ports": [
{
"id": "rgb2.A",
"width": 0,
"height": 0,
"x": 0,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "rgb2.label.ref",
"text": "rgb2",
"x": "15",
"y": -10,
"height": 11,
"width": 24
}
]
},
{
"id": "usb_dp",
"width": 30,
"height": 20,
"ports": [
{
"id": "usb_dp.A",
"width": 0,
"height": 0,
"x": 0,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "usb_dp.label.ref",
"text": "usb_dp",
"x": "15",
"y": -10,
"height": 11,
"width": 36
}
]
},
{
"id": "usb_dn",
"width": 30,
"height": 20,
"ports": [
{
"id": "usb_dn.A",
"width": 0,
"height": 0,
"x": 0,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "usb_dn.label.ref",
"text": "usb_dn",
"x": "15",
"y": -10,
"height": 11,
"width": 36
}
]
},
{
"id": "usb_dp_pu",
"width": 30,
"height": 20,
"ports": [
{
"id": "usb_dp_pu.A",
"width": 0,
"height": 0,
"x": 0,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "usb_dp_pu.label.ref",
"text": "usb_dp_pu",
"x": "15",
"y": -10,
"height": 11,
"width": 54
}
]
},
{
"id": "1",
"width": 30,
"height": 20,
"ports": [
{
"id": "1.Y",
"width": 0,
"height": 0,
"x": 31,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "1.label.ref",
"text": "1",
"x": "15",
"y": -10,
"height": 11,
"width": 6
}
]
},
{
"id": "0",
"width": 30,
"height": 20,
"ports": [
{
"id": "0.Y",
"width": 0,
"height": 0,
"x": 31,
"y": 10
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": [
{
"id": "0.label.ref",
"text": "0",
"x": "15",
"y": -10,
"height": 11,
"width": 6
}
]
},
{
"id": "$split$,6,7,8,",
"width": 5,
"height": 60,
"ports": [
{
"id": "$split$,6,7,8,.A",
"width": 1,
"height": 1,
"x": 0,
"y": 20
},
{
"id": "$split$,6,7,8,.2",
"width": 1,
"height": 1,
"x": 4,
"y": 10,
"labels": [
{
"id": "$split$,6,7,8,.2.label",
"text": "2",
"x": -5,
"y": -10,
"width": 6,
"height": 11
}
]
},
{
"id": "$split$,6,7,8,.1",
"width": 1,
"height": 1,
"x": 4,
"y": 30
},
{
"id": "$split$,6,7,8,.0",
"width": 1,
"height": 1,
"x": 4,
"y": 50
}
],
"layoutOptions": {
"org.eclipse.elk.portConstraints": "FIXED_POS"
},
"labels": []
}
],
"edges": [
{
"id": "e0",
"sources": [
"clki.Y"
],
"targets": [
"clk_generator.clk"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e1",
"sources": [
"1.Y"
],
"targets": [
"rgba_driver.CURREN"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e2",
"sources": [
"1.Y"
],
"targets": [
"rgba_driver.RGBLEDEN"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e3",
"sources": [
"$split$,6,7,8,.2"
],
"targets": [
"rgba_driver.RGB0PWM"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e4",
"sources": [
"$split$,6,7,8,.1"
],
"targets": [
"rgba_driver.RGB1PWM"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e5",
"sources": [
"$split$,6,7,8,.0"
],
"targets": [
"rgba_driver.RGB2PWM"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e6",
"sources": [
"rgba_driver.RGB0"
],
"targets": [
"rgb0.A"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e7",
"sources": [
"rgba_driver.RGB1"
],
"targets": [
"rgb1.A"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e8",
"sources": [
"rgba_driver.RGB2"
],
"targets": [
"rgb2.A"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e9",
"sources": [
"0.Y"
],
"targets": [
"usb_dp.A"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e10",
"sources": [
"0.Y"
],
"targets": [
"usb_dn.A"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e11",
"sources": [
"0.Y"
],
"targets": [
"usb_dp_pu.A"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 1
}
},
{
"id": "e12",
"labels": [
{
"id": "",
"text": "3",
"width": 4,
"height": 6,
"x": 0,
"y": 0,
"layoutOptions": {
"org.eclipse.elk.edgeLabels.inline": true
}
}
],
"sources": [
"clk_generator.cnt"
],
"targets": [
"$split$,6,7,8,.A"
],
"layoutOptions": {
"org.eclipse.elk.layered.priority.direction": 10,
"org.eclipse.elk.edge.thickness": 2
}
}
]
}
What I'm thinking about is if it'd be possible to add an option to netlistsvg to export this ELK JSON, and then have d3-hwschematic import it, maybe with minor modifications. The variable kgraph here is where this JSON/object is generated/stored. This way, d3-hwschematic could generate diagrams for VHDL/Verilog, and netlistsvg could have a new "frontend".
Internally, netlistsvg generates a JSON object very similar to the ELK JSON used by this project. For example, using one of the Fomu blink examples, this is generated by netlistsvg:
And this is the corresponding ELK JSON before being handed off to ELK for rendering into an SVG:
Details
{ "id": "Fomu_Blink", "children": [ { "id": "clk_generator", "width": 30, "height": 20, "ports": [ { "id": "clk_generator.clk", "width": 1, "height": 1, "x": 0, "y": 10, "labels": [ { "id": "clk_generator.clk.label", "text": "clk", "x": -13, "y": -10, "width": 18, "height": 11 } ] }, { "id": "clk_generator.cnt", "width": 1, "height": 1, "x": 30, "y": 10, "labels": [ { "id": "clk_generator.cnt.label", "text": "cnt", "x": -5, "y": -10, "width": 18, "height": 11 } ] } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "clk_generator.label.ref", "text": "clk_generator", "x": "15", "y": -10, "height": 11, "width": 78 } ] }, { "id": "rgba_driver", "width": 30, "height": 100, "ports": [ { "id": "rgba_driver.CURREN", "width": 1, "height": 1, "x": 0, "y": 10, "labels": [ { "id": "rgba_driver.CURREN.label", "text": "CURREN", "x": -13, "y": -10, "width": 36, "height": 11 } ] }, { "id": "rgba_driver.RGB0PWM", "width": 1, "height": 1, "x": 0, "y": 30, "labels": [ { "id": "rgba_driver.RGB0PWM.label", "text": "RGB0PWM", "x": -13, "y": -10, "width": 42, "height": 11 } ] }, { "id": "rgba_driver.RGB1PWM", "width": 1, "height": 1, "x": 0, "y": 50, "labels": [ { "id": "rgba_driver.RGB1PWM.label", "text": "RGB1PWM", "x": -13, "y": -10, "width": 42, "height": 11 } ] }, { "id": "rgba_driver.RGB2PWM", "width": 1, "height": 1, "x": 0, "y": 70, "labels": [ { "id": "rgba_driver.RGB2PWM.label", "text": "RGB2PWM", "x": -13, "y": -10, "width": 42, "height": 11 } ] }, { "id": "rgba_driver.RGBLEDEN", "width": 1, "height": 1, "x": 0, "y": 90, "labels": [ { "id": "rgba_driver.RGBLEDEN.label", "text": "RGBLEDEN", "x": -13, "y": -10, "width": 48, "height": 11 } ] }, { "id": "rgba_driver.RGB0", "width": 1, "height": 1, "x": 30, "y": 10, "labels": [ { "id": "rgba_driver.RGB0.label", "text": "RGB0", "x": -5, "y": -10, "width": 24, "height": 11 } ] }, { "id": "rgba_driver.RGB1", "width": 1, "height": 1, "x": 30, "y": 30, "labels": [ { "id": "rgba_driver.RGB1.label", "text": "RGB1", "x": -5, "y": -10, "width": 24, "height": 11 } ] }, { "id": "rgba_driver.RGB2", "width": 1, "height": 1, "x": 30, "y": 50, "labels": [ { "id": "rgba_driver.RGB2.label", "text": "RGB2", "x": -5, "y": -10, "width": 24, "height": 11 } ] } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "rgba_driver.label.ref", "text": "rgba_driver", "x": "15", "y": -10, "height": 11, "width": 66 } ] }, { "id": "clki", "width": 30, "height": 20, "ports": [ { "id": "clki.Y", "width": 0, "height": 0, "x": 30, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "clki.label.ref", "text": "clki", "x": "15", "y": -10, "height": 11, "width": 24 } ] }, { "id": "rgb0", "width": 30, "height": 20, "ports": [ { "id": "rgb0.A", "width": 0, "height": 0, "x": 0, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "rgb0.label.ref", "text": "rgb0", "x": "15", "y": -10, "height": 11, "width": 24 } ] }, { "id": "rgb1", "width": 30, "height": 20, "ports": [ { "id": "rgb1.A", "width": 0, "height": 0, "x": 0, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "rgb1.label.ref", "text": "rgb1", "x": "15", "y": -10, "height": 11, "width": 24 } ] }, { "id": "rgb2", "width": 30, "height": 20, "ports": [ { "id": "rgb2.A", "width": 0, "height": 0, "x": 0, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "rgb2.label.ref", "text": "rgb2", "x": "15", "y": -10, "height": 11, "width": 24 } ] }, { "id": "usb_dp", "width": 30, "height": 20, "ports": [ { "id": "usb_dp.A", "width": 0, "height": 0, "x": 0, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "usb_dp.label.ref", "text": "usb_dp", "x": "15", "y": -10, "height": 11, "width": 36 } ] }, { "id": "usb_dn", "width": 30, "height": 20, "ports": [ { "id": "usb_dn.A", "width": 0, "height": 0, "x": 0, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "usb_dn.label.ref", "text": "usb_dn", "x": "15", "y": -10, "height": 11, "width": 36 } ] }, { "id": "usb_dp_pu", "width": 30, "height": 20, "ports": [ { "id": "usb_dp_pu.A", "width": 0, "height": 0, "x": 0, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "usb_dp_pu.label.ref", "text": "usb_dp_pu", "x": "15", "y": -10, "height": 11, "width": 54 } ] }, { "id": "1", "width": 30, "height": 20, "ports": [ { "id": "1.Y", "width": 0, "height": 0, "x": 31, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "1.label.ref", "text": "1", "x": "15", "y": -10, "height": 11, "width": 6 } ] }, { "id": "0", "width": 30, "height": 20, "ports": [ { "id": "0.Y", "width": 0, "height": 0, "x": 31, "y": 10 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [ { "id": "0.label.ref", "text": "0", "x": "15", "y": -10, "height": 11, "width": 6 } ] }, { "id": "$split$,6,7,8,", "width": 5, "height": 60, "ports": [ { "id": "$split$,6,7,8,.A", "width": 1, "height": 1, "x": 0, "y": 20 }, { "id": "$split$,6,7,8,.2", "width": 1, "height": 1, "x": 4, "y": 10, "labels": [ { "id": "$split$,6,7,8,.2.label", "text": "2", "x": -5, "y": -10, "width": 6, "height": 11 } ] }, { "id": "$split$,6,7,8,.1", "width": 1, "height": 1, "x": 4, "y": 30 }, { "id": "$split$,6,7,8,.0", "width": 1, "height": 1, "x": 4, "y": 50 } ], "layoutOptions": { "org.eclipse.elk.portConstraints": "FIXED_POS" }, "labels": [] } ], "edges": [ { "id": "e0", "sources": [ "clki.Y" ], "targets": [ "clk_generator.clk" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e1", "sources": [ "1.Y" ], "targets": [ "rgba_driver.CURREN" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e2", "sources": [ "1.Y" ], "targets": [ "rgba_driver.RGBLEDEN" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e3", "sources": [ "$split$,6,7,8,.2" ], "targets": [ "rgba_driver.RGB0PWM" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e4", "sources": [ "$split$,6,7,8,.1" ], "targets": [ "rgba_driver.RGB1PWM" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e5", "sources": [ "$split$,6,7,8,.0" ], "targets": [ "rgba_driver.RGB2PWM" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e6", "sources": [ "rgba_driver.RGB0" ], "targets": [ "rgb0.A" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e7", "sources": [ "rgba_driver.RGB1" ], "targets": [ "rgb1.A" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e8", "sources": [ "rgba_driver.RGB2" ], "targets": [ "rgb2.A" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e9", "sources": [ "0.Y" ], "targets": [ "usb_dp.A" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e10", "sources": [ "0.Y" ], "targets": [ "usb_dn.A" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e11", "sources": [ "0.Y" ], "targets": [ "usb_dp_pu.A" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 1 } }, { "id": "e12", "labels": [ { "id": "", "text": "3", "width": 4, "height": 6, "x": 0, "y": 0, "layoutOptions": { "org.eclipse.elk.edgeLabels.inline": true } } ], "sources": [ "clk_generator.cnt" ], "targets": [ "$split$,6,7,8,.A" ], "layoutOptions": { "org.eclipse.elk.layered.priority.direction": 10, "org.eclipse.elk.edge.thickness": 2 } } ] }Trying to import this directly, I had to change
layoutOptionstopropertiesand add emptyhwMetafor the different nodes, but still came up with errors. I'm also not that familiar with this format so you may be able to see something I can't.What I'm thinking about is if it'd be possible to add an option to netlistsvg to export this ELK JSON, and then have d3-hwschematic import it, maybe with minor modifications. The variable
kgraphhere is where this JSON/object is generated/stored. This way, d3-hwschematic could generate diagrams for VHDL/Verilog, and netlistsvg could have a new "frontend".