Merge pull request #237 from Microsoft/power-usage

finer grain power wires based on usage
This commit is contained in:
Peli de Halleux 2016-09-02 16:07:02 -07:00 committed by GitHub
commit cebded2526
2 changed files with 111 additions and 32 deletions

View File

@ -55,6 +55,12 @@ namespace pxsim {
gpioNeeded: number, gpioNeeded: number,
gpioAssigned: string[] gpioAssigned: string[]
} }
interface PowerUsage {
topGround: boolean,
topThreeVolt: boolean,
bottomGround: boolean,
bottomThreeVolt: boolean,
}
function copyDoubleArray(a: string[][]) { function copyDoubleArray(a: string[][]) {
return a.map(b => b.map(p => p)); return a.map(b => b.map(p => p));
} }
@ -98,8 +104,7 @@ namespace pxsim {
private allocateLocation(location: WireLocationDefinition, opts: AllocLocOpts): Loc { private allocateLocation(location: WireLocationDefinition, opts: AllocLocOpts): Loc {
if (location === "ground" || location === "threeVolt") { if (location === "ground" || location === "threeVolt") {
U.assert(!!opts.nearestBBPin); U.assert(!!opts.nearestBBPin);
let nearLoc = opts.nearestBBPin; let nearestCoord = this.opts.getBBCoord(opts.nearestBBPin);
let nearestCoord = this.opts.getBBCoord(nearLoc);
let firstTopAndBot = [ let firstTopAndBot = [
this.availablePowerPins.top.ground[0] || this.availablePowerPins.top.threeVolt[0], this.availablePowerPins.top.ground[0] || this.availablePowerPins.top.threeVolt[0],
this.availablePowerPins.bottom.ground[0] || this.availablePowerPins.bottom.threeVolt[0] this.availablePowerPins.bottom.ground[0] || this.availablePowerPins.bottom.threeVolt[0]
@ -111,31 +116,31 @@ namespace pxsim {
//TODO //TODO
} }
let nearTop = visuals.findClosestCoordIdx(nearestCoord, firstTopAndBot) == 0; let nearTop = visuals.findClosestCoordIdx(nearestCoord, firstTopAndBot) == 0;
let pins: BBRowCol[]; let barPins: BBRowCol[];
if (nearTop) { if (nearTop) {
if (location === "ground") { if (location === "ground") {
pins = this.availablePowerPins.top.ground; barPins = this.availablePowerPins.top.ground;
} else if (location === "threeVolt") { } else if (location === "threeVolt") {
pins = this.availablePowerPins.top.threeVolt; barPins = this.availablePowerPins.top.threeVolt;
} }
} else { } else {
if (location === "ground") { if (location === "ground") {
pins = this.availablePowerPins.bottom.ground; barPins = this.availablePowerPins.bottom.ground;
} else if (location === "threeVolt") { } else if (location === "threeVolt") {
pins = this.availablePowerPins.bottom.threeVolt; barPins = this.availablePowerPins.bottom.threeVolt;
} }
} }
let pinCoords = pins.map(rowCol => { let pinCoords = barPins.map(rowCol => {
return this.opts.getBBCoord(rowCol); return this.opts.getBBCoord(rowCol);
}); });
let pinIdx = visuals.findClosestCoordIdx(nearestCoord, pinCoords); let closestPinIdx = visuals.findClosestCoordIdx(nearestCoord, pinCoords);
let pin = pins[pinIdx]; let pin = barPins[closestPinIdx];
if (nearTop) { if (nearTop) {
this.availablePowerPins.top.ground.splice(pinIdx, 1); this.availablePowerPins.top.ground.splice(closestPinIdx, 1);
this.availablePowerPins.top.threeVolt.splice(pinIdx, 1); this.availablePowerPins.top.threeVolt.splice(closestPinIdx, 1);
} else { } else {
this.availablePowerPins.bottom.ground.splice(pinIdx, 1); this.availablePowerPins.bottom.ground.splice(closestPinIdx, 1);
this.availablePowerPins.bottom.threeVolt.splice(pinIdx, 1); this.availablePowerPins.bottom.threeVolt.splice(closestPinIdx, 1);
} }
return {type: "breadboard", rowCol: pin}; return {type: "breadboard", rowCol: pin};
} else if (location[0] === "breadboard") { } else if (location[0] === "breadboard") {
@ -164,7 +169,7 @@ namespace pxsim {
return null; return null;
} }
} }
private allocatePowerWires(): WireInst[] { private allocatePowerWires(powerUsage: PowerUsage): WireInst[] {
let boardGround = this.opts.boardDef.groundPins[0] || null; let boardGround = this.opts.boardDef.groundPins[0] || null;
if (!boardGround) { if (!boardGround) {
console.log("No available ground pin on board!"); console.log("No available ground pin on board!");
@ -189,30 +194,91 @@ namespace pxsim {
} }
const GROUND_COLOR = "blue"; const GROUND_COLOR = "blue";
const POWER_COLOR = "red"; const POWER_COLOR = "red";
const wires: WireInst[] = [ const wires: WireInst[] = [];
{start: this.allocateLocation("ground", {nearestBBPin: top}), let groundStep = 0;
let threeVoltStep = (powerUsage.bottomGround || powerUsage.topGround) ? 1 : 0;
if (powerUsage.bottomGround && powerUsage.topGround) {
//bb top - <==> bb bot -
wires.push({
start: this.allocateLocation("ground", {nearestBBPin: top}),
end: this.allocateLocation("ground", {nearestBBPin: bot}), end: this.allocateLocation("ground", {nearestBBPin: bot}),
color: GROUND_COLOR, assemblyStep: 0}, color: GROUND_COLOR, assemblyStep: groundStep
{start: this.allocateLocation("ground", {nearestBBPin: top}), });
}
if (powerUsage.topGround) {
//board - <==> bb top -
wires.push({
start: this.allocateLocation("ground", {nearestBBPin: top}),
end: {type: "dalboard", pin: boardGround}, end: {type: "dalboard", pin: boardGround},
color: GROUND_COLOR, assemblyStep: 0}, color: GROUND_COLOR, assemblyStep: groundStep
{start: this.allocateLocation("threeVolt", {nearestBBPin: top}), });
} else if (powerUsage.bottomGround) {
//board - <==> bb bot -
wires.push({
start: this.allocateLocation("ground", {nearestBBPin: bot}),
end: {type: "dalboard", pin: boardGround},
color: GROUND_COLOR, assemblyStep: groundStep
});
}
if (powerUsage.bottomThreeVolt && powerUsage.bottomGround) {
//bb top + <==> bb bot +
wires.push({
start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
end: this.allocateLocation("threeVolt", {nearestBBPin: bot}), end: this.allocateLocation("threeVolt", {nearestBBPin: bot}),
color: POWER_COLOR, assemblyStep: 1}, color: POWER_COLOR, assemblyStep: threeVoltStep
{start: this.allocateLocation("threeVolt", {nearestBBPin: top}), });
}
if (powerUsage.topThreeVolt) {
//board + <==> bb top +
wires.push({
start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
end: {type: "dalboard", pin: threeVoltPin}, end: {type: "dalboard", pin: threeVoltPin},
color: POWER_COLOR, assemblyStep: 1}, color: POWER_COLOR, assemblyStep: threeVoltStep
]; });
} else if (powerUsage.bottomThreeVolt) {
//board + <==> bb bot +
wires.push({
start: this.allocateLocation("threeVolt", {nearestBBPin: bot}),
end: {type: "dalboard", pin: threeVoltPin},
color: POWER_COLOR, assemblyStep: threeVoltStep
});
}
return wires; return wires;
} }
private isOnBreadboardBottom(location: WireLocationDefinition) {
let isBot = false;
if (location[0] === "breadboard") {
let row = <string>location[1];
isBot = 0 <= ["a", "b", "c", "d", "e"].indexOf(row);
}
return isBot;
}
private computePowerUsage(wireDef: WireDefinition): PowerUsage {
let arrAny = (a: boolean[]) => a.reduce((p, n) => p || n, false);
let ends = [wireDef.start, wireDef.end];
let endIsGround = ends.map(e => e === "ground");
let endIsThreeVolt = ends.map(e => e === "threeVolt");
let endIsBot = ends.map(e => this.isOnBreadboardBottom(e));
let hasGround = arrAny(endIsGround);
let hasThreeVolt = arrAny(endIsThreeVolt);
let hasBot = arrAny(endIsBot);
return {
topGround: hasGround && !hasBot,
topThreeVolt: hasThreeVolt && !hasBot,
bottomGround: hasGround && hasBot,
bottomThreeVolt: hasThreeVolt && hasBot
};
}
private allocateWire(wireDef: WireDefinition, opts: AllocWireOpts): WireInst { private allocateWire(wireDef: WireDefinition, opts: AllocWireOpts): WireInst {
let ends = [wireDef.start, wireDef.end]; let ends = [wireDef.start, wireDef.end];
let endIsPower = ends.map(e => e === "ground" || e === "threeVolt"); let endIsPower = ends.map(e => e === "ground" || e === "threeVolt");
//allocate non-power first so we know the nearest pin for the power end
let endInsts = ends.map((e, idx) => !endIsPower[idx] ? this.allocateLocation(e, opts) : null) let endInsts = ends.map((e, idx) => !endIsPower[idx] ? this.allocateLocation(e, opts) : null)
//allocate power pins closest to the other end of the wire
endInsts = endInsts.map((e, idx) => { endInsts = endInsts.map((e, idx) => {
if (e) if (e)
return e; return e;
let locInst = <BBLoc>endInsts[1 - idx]; let locInst = <BBLoc>endInsts[1 - idx]; // non-power end
let l = this.allocateLocation(ends[idx], { let l = this.allocateLocation(ends[idx], {
nearestBBPin: locInst.rowCol, nearestBBPin: locInst.rowCol,
startColumn: opts.startColumn, startColumn: opts.startColumn,
@ -414,8 +480,21 @@ namespace pxsim {
let basicWires: WireInst[] = []; let basicWires: WireInst[] = [];
let cmpsAndWires: CmpAndWireInst[] = []; let cmpsAndWires: CmpAndWireInst[] = [];
if (cmpList.length > 0) { if (cmpList.length > 0) {
basicWires = this.allocatePowerWires();
let partialCmps = this.allocatePartialCmps(); let partialCmps = this.allocatePartialCmps();
let allWireDefs = partialCmps.map(p => p.def.wires).reduce((p, n) => p.concat(n), []);
let wirePowerUsage = allWireDefs.map(w => this.computePowerUsage(w));
let powerUsage = wirePowerUsage.reduce((p, n) => ({
topGround: p.topGround || n.topGround,
topThreeVolt: p.topThreeVolt || n.topThreeVolt,
bottomGround: p.bottomGround || n.bottomGround,
bottomThreeVolt: p.bottomThreeVolt || n.bottomThreeVolt
}), {
topGround: false,
topThreeVolt: false,
bottomGround: false,
bottomThreeVolt: false,
});
basicWires = this.allocatePowerWires(powerUsage);
let cmpGPIOPins = this.allocateGPIOPins(partialCmps); let cmpGPIOPins = this.allocateGPIOPins(partialCmps);
let reverseMap = mkReverseMap(this.opts.boardDef.gpioPinMap); let reverseMap = mkReverseMap(this.opts.boardDef.gpioPinMap);
let cmpMicrobitPins = cmpGPIOPins.map(pins => pins.map(p => reverseMap[p])); let cmpMicrobitPins = cmpGPIOPins.map(pins => pins.map(p => reverseMap[p]));

View File

@ -321,7 +321,7 @@ namespace pxsim.instructions {
(stepToWires[step] || (stepToWires[step] = [])).push(w) (stepToWires[step] || (stepToWires[step] = [])).push(w)
}); });
let getMaxStep = (ns: {assemblyStep: number}[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0); let getMaxStep = (ns: {assemblyStep: number}[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
let stepOffset = getMaxStep(powerWires) + 2; let stepOffset = powerWires.length > 0 ? getMaxStep(powerWires) + 2 : 1;
components.forEach(cAndWs => { components.forEach(cAndWs => {
let {component, wires} = cAndWs; let {component, wires} = cAndWs;
let cStep = component.assemblyStep + stepOffset; let cStep = component.assemblyStep + stepOffset;