Skip to content

Commit 6cb6176

Browse files
committed
Initial experiment with orienting components
1 parent 68c1ed9 commit 6cb6176

File tree

4 files changed

+214
-15
lines changed

4 files changed

+214
-15
lines changed

bin/netlistsvg.js

100644100755
File mode changed.

examples/analog/resistor_divider.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"cells": {
1111
"r1": {
12-
"type": "r_v",
12+
"type": "r",
1313
"port_directions": {
1414
"A": "input",
1515
"B": "output"
@@ -20,7 +20,7 @@
2020
}
2121
},
2222
"r2": {
23-
"type": "r_v",
23+
"type": "r",
2424
"port_directions": {
2525
"A": "input",
2626
"B": "output"

lib/combinations.js

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/**
2+
* Copyright 2012 Akseli Palén.
3+
* Created 2012-07-15.
4+
* Licensed under the MIT license.
5+
*
6+
* <license>
7+
* Permission is hereby granted, free of charge, to any person obtaining
8+
* a copy of this software and associated documentation files
9+
* (the "Software"), to deal in the Software without restriction,
10+
* including without limitation the rights to use, copy, modify, merge,
11+
* publish, distribute, sublicense, and/or sell copies of the Software,
12+
* and to permit persons to whom the Software is furnished to do so,
13+
* subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be
16+
* included in all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
* SOFTWARE.
26+
* </lisence>
27+
*
28+
* Implements functions to calculate combinations of elements in JS Arrays.
29+
*
30+
* Functions:
31+
* k_combinations(set, k) -- Return all k-sized combinations in a set
32+
* combinations(set) -- Return all combinations of the set
33+
*/
34+
35+
36+
/**
37+
* K-combinations
38+
*
39+
* Get k-sized combinations of elements in a set.
40+
*
41+
* Usage:
42+
* k_combinations(set, k)
43+
*
44+
* Parameters:
45+
* set: Array of objects of any type. They are treated as unique.
46+
* k: size of combinations to search for.
47+
*
48+
* Return:
49+
* Array of found combinations, size of a combination is k.
50+
*
51+
* Examples:
52+
*
53+
* k_combinations([1, 2, 3], 1)
54+
* -> [[1], [2], [3]]
55+
*
56+
* k_combinations([1, 2, 3], 2)
57+
* -> [[1,2], [1,3], [2, 3]
58+
*
59+
* k_combinations([1, 2, 3], 3)
60+
* -> [[1, 2, 3]]
61+
*
62+
* k_combinations([1, 2, 3], 4)
63+
* -> []
64+
*
65+
* k_combinations([1, 2, 3], 0)
66+
* -> []
67+
*
68+
* k_combinations([1, 2, 3], -1)
69+
* -> []
70+
*
71+
* k_combinations([], 0)
72+
* -> []
73+
*/
74+
function k_combinations(set, k) {
75+
var i, j, combs, head, tailcombs;
76+
77+
// There is no way to take e.g. sets of 5 elements from
78+
// a set of 4.
79+
if (k > set.length || k <= 0) {
80+
return [];
81+
}
82+
83+
// K-sized set has only one K-sized subset.
84+
if (k == set.length) {
85+
return [set];
86+
}
87+
88+
// There is N 1-sized subsets in a N-sized set.
89+
if (k == 1) {
90+
combs = [];
91+
for (i = 0; i < set.length; i++) {
92+
combs.push([set[i]]);
93+
}
94+
return combs;
95+
}
96+
97+
// Assert {1 < k < set.length}
98+
99+
// Algorithm description:
100+
// To get k-combinations of a set, we want to join each element
101+
// with all (k-1)-combinations of the other elements. The set of
102+
// these k-sized sets would be the desired result. However, as we
103+
// represent sets with lists, we need to take duplicates into
104+
// account. To avoid producing duplicates and also unnecessary
105+
// computing, we use the following approach: each element i
106+
// divides the list into three: the preceding elements, the
107+
// current element i, and the subsequent elements. For the first
108+
// element, the list of preceding elements is empty. For element i,
109+
// we compute the (k-1)-computations of the subsequent elements,
110+
// join each with the element i, and store the joined to the set of
111+
// computed k-combinations. We do not need to take the preceding
112+
// elements into account, because they have already been the i:th
113+
// element so they are already computed and stored. When the length
114+
// of the subsequent list drops below (k-1), we cannot find any
115+
// (k-1)-combs, hence the upper limit for the iteration:
116+
combs = [];
117+
for (i = 0; i < set.length - k + 1; i++) {
118+
// head is a list that includes only our current element.
119+
head = set.slice(i, i + 1);
120+
// We take smaller combinations from the subsequent elements
121+
tailcombs = k_combinations(set.slice(i + 1), k - 1);
122+
// For each (k-1)-combination we join it with the current
123+
// and store it to the set of k-combinations.
124+
for (j = 0; j < tailcombs.length; j++) {
125+
combs.push(head.concat(tailcombs[j]));
126+
}
127+
}
128+
return combs;
129+
}
130+
131+
132+
/**
133+
* Combinations
134+
*
135+
* Get all possible combinations of elements in a set.
136+
*
137+
* Usage:
138+
* combinations(set)
139+
*
140+
* Examples:
141+
*
142+
* combinations([1, 2, 3])
143+
* -> [[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
144+
*
145+
* combinations([1])
146+
* -> [[1]]
147+
*/
148+
function combinations(set) {
149+
var k, i, combs, k_combs;
150+
combs = [];
151+
152+
// Calculate all non-empty k-combinations
153+
for (k = 1; k <= set.length; k++) {
154+
k_combs = k_combinations(set, k);
155+
for (i = 0; i < k_combs.length; i++) {
156+
combs.push(k_combs[i]);
157+
}
158+
}
159+
return combs;
160+
}
161+
162+
module.exports = combinations

lib/index.js

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
var onml = require('onml'),
44
_ = require('lodash'),
55
ELK = require('elkjs'),
6-
// fs = require('fs-extra'),
6+
combinations = require('./combinations'),
77
clone = require('clone');
88

99
var elk = new ELK();
@@ -26,19 +26,56 @@ function render(skin_data, yosys_netlist, done) {
2626
}
2727

2828
var module = getReformattedModule(yosys_netlist.modules[module_name], skin);
29-
// this can be skipped if there are no 0's or 1's
30-
if (layoutProps.constants !== false) {
31-
addConstants(module);
32-
}
33-
// this can be skipped if there are no splits or joins
34-
if (layoutProps.splitsAndJoins !== false) {
35-
addSplitsJoins(module);
36-
}
37-
createWires(module, skin);
38-
var kgraph = buildKGraph(module, module_name, skin);
3929

40-
const promise = elk.layout(kgraph, {layoutOptions: layoutProps.layoutEngine})
41-
.then(g => klayed_out(g, module, skin));
30+
const components = module.nodes.filter(n => n.type === 'r').map(n => n.key)
31+
32+
const verticalNodeCombinations = [[]].concat(combinations(components))
33+
34+
const promises = verticalNodeCombinations.map(verticals => {
35+
36+
const m = JSON.parse(JSON.stringify(module))
37+
38+
for (const n of m.nodes) {
39+
if (n.type === 'r') {
40+
if (verticals.includes(n.key)) {
41+
n.type += '_v'
42+
} else {
43+
n.type += '_h'
44+
}
45+
}
46+
}
47+
48+
// this can be skipped if there are no 0's or 1's
49+
if (layoutProps.constants !== false) {
50+
addConstants(m);
51+
}
52+
// this can be skipped if there are no splits or joins
53+
if (layoutProps.splitsAndJoins !== false) {
54+
addSplitsJoins(m);
55+
}
56+
createWires(m, skin);
57+
58+
59+
var kgraph = buildKGraph(m, module_name, skin);
60+
61+
return elk.layout(kgraph, {layoutOptions: layoutProps.layoutEngine}).then(g => [g,m])
62+
})
63+
64+
const promise = Promise.all(promises).then(graphs => {
65+
66+
console.log('<div style="display:flex">')
67+
68+
for (const [g,m] of graphs) {
69+
console.log('<div style="border:1px solid lightgrey;margin:10px;padding:10px;">')
70+
console.log(klayed_out(g, m, skin))
71+
console.log('width:', g.width)
72+
console.log('</div>')
73+
}
74+
75+
console.log('</div>')
76+
77+
})
78+
4279

4380
// support legacy callback style
4481
if (typeof done === 'function') {

0 commit comments

Comments
 (0)