<html>
<head>
<title>Logisim Part Design Generator</title>
<script>
var hDesigner;
var hDesign;
var hModel;
function draw() {
const ctx = hDesign;
const dsg = hDesigner.value.split(/\r?\n/);
//
var model = [];
//
let fnt = {
PIDS :"9px Serif",
PINS :"7px Serif"
};
let part = "";
let mode;
let i;
let y = 0;
let maxy = 0;
let space;
let measure;
//
function setPin(font, anchor, x, y, text, circle) {
model.push(' <text font-family="' + font.split(" ")[1] + '" font-size="' + parseInt(font) + '" text-anchor="' + anchor + '" x="' + x + '" y="' + y + '">' + text + '</text>');
if(circle < 0 || circle > 0) {
model.push(' <ellipse cx="' + x + '" cy="' + (y - 3) + '" fill="none" rx="3.0" ry="3.0" stroke="#000000" stroke-width="2"/>');
model.push(' <polyline fill="none" points="' + x + ',' + (y - 8) + ',' + (x + 24 * circle) + ',' + (y - 8) +'" stroke="#000000" stroke-width="1"/>');
}
}
//
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
for(const str of dsg) {
const rex = /([-.]|(\d+)([:;]\d+)*(_?)([A-Z]+)?(\d+)?(:(\d+))?(["']?))/ig;
const rxp = /[-.]|(\d+)(([:;]\d+)+)?(_?)([A-Z]+)((\d+)?(:\d+)?)(["']?)/i;
const dsc = (/(\w+)?\t*(.+)?/i).exec(str);
var data;
var last;
var order;
var names;
var pin;
if(dsc[1] != "")
mode = dsc[1],
y = 20;
if(mode in fnt)
fnt[mode] = dsc[2];
else
if(dsc[2]) {
for(const pin of dsc[2].match(rex)) {
if(pin) {
if(pin == "-") {
y += 10;
ctx.beginPath();
switch(mode) {
case "PINPUT":
ctx.moveTo(19, y);
ctx.lineTo(49, y);
model.push(``);
break;
case "PINOUT":
ctx.moveTo(122, y);
ctx.lineTo(92, y);
break;
}
ctx.stroke();
} else
if(pin != ".") {
data = pin.match(rxp);
if(data) {
last = parseInt(data[1]);
order = [last];
if(data[2]) {
for(const col of data[2].match(/[:;]\d+/g)) {
const next = parseInt(col.substr(1));
if(col.charAt(0) == ";")
order.push(last = next);
else
if(last < next)
while(last < next)
order.push(++ last);
else
while(last > next)
order.push(-- last);
}
}
last = parseInt(data[6]);
names = [last];
if(data[8]) {
for(const col of data[8].match(/[:;]\d+/g)) {
const next = parseInt(col.substr(1));
if(col.charAt(0) == ";")
names.push(last = next);
else
if(last < next)
while(last < next)
names.push(++ last);
else
while(last > next)
names.push(-- last);
}
} else
names = [data[6]];
}
if(data)
space = data[9] == '"' ? 30 : data[9] == "'" ? 20 : 10;
else
space = 10;
switch(mode) {
case "PART":
part = dsc[2].split(/\t+|\s+/);
break;
case "PINPUT":
ctx.beginPath();
i = 0;
ctx.font = fnt.PINS;
ctx.textAlign = "right";
for(const id of order) {
setPin(fnt.PINS, "end", 19 ,y + space * i + 8, id);
ctx.strokeText(id, 19, y + space * i ++ + 8);
}
i = 0;
ctx.font = fnt.PIDS;
ctx.textAlign = "left";
for(const id of names) {
if(data[4] == "_") {
ctx.ellipse(19, y + space * i + 10, 2, 2, 0, 0, 2 * Math.PI, true);
measure = ctx.measureText(data[5] + id);
ctx.moveTo(22, y + space * i + 5);
ctx.lineTo(22 + measure.width, y + space * i + 5);
}
setPin(fnt.PIDS, "start", 22, y + space * i + 13, data[5] + id, data[4] ? +1 : 0);
ctx.strokeText(data[5] + id, 22, y + space * i + 13);
++ i;
}
ctx.stroke();
y += space * (i - 1) + 10;
break;
case "PINOUT":
data = pin.match(rxp);
ctx.beginPath();
i = 0;
ctx.font = fnt.PINS;
ctx.textAlign = "left";
for(const id of order) {
setPin(fnt.PINS, "start", 122 ,y + space * i + 8, id);
ctx.strokeText(id, 122, y + space * i ++ + 8);
}
i = 0;
ctx.font = fnt.PIDS;
ctx.textAlign = "right";
for(const id of names) {
if(data[4] == "_") {
ctx.ellipse(122, y + space * i + 10, 2, 2, 0, 0, 2 * Math.PI, true);
measure = ctx.measureText(data[5] + id);
ctx.moveTo(122, y + space * i + 5);
ctx.lineTo(122 - measure.width, y + space * i + 5);
}
setPin(fnt.PIDS, "end", 119, y + space * i + 13, data[5] + id, data[4] ? -1 : 0);
ctx.strokeText(data[5] + id, 119, y + space * i ++ + 13);
}
ctx.stroke();
y += space * (i - 1) + 10;
break;
}
} else
y += 10;
} else
y += 10;
}
}
maxy = Math.max(maxy, y);
}
ctx.beginPath();
ctx.rect(19, 10, 103, maxy);
ctx.moveTo(49, 10);
ctx.lineTo(49, 10 + maxy);
ctx.moveTo(92, 10);
ctx.lineTo(92, 10 + maxy);
ctx.textAlign = "center";
ctx.strokeText(part[1], 70, 20);
ctx.strokeText(part[2], 70, maxy);
ctx.stroke();
setPin(fnt.PIDS, "center", 70, 20, part[1]);
setPin(fnt.PIDS, "center", 70, maxy, part[2]);
hModel.value = model.join("\r\n");
}
function main() {
hModel = document.getElementById("Model");
hDesigner = document.getElementById("Designer");
hDesigner.addEventListener("keyup", draw);
hDesign = document.getElementById("Design").getContext("2d");
draw();
}
</script>
<style>
body {
background-color:silver;
}
</style>
</head>
<body>
<textarea id=Designer rows=6 cols=100 onkeyup='draw()'>
PINS 7px Serif
PIDS 9px Serif
PART I8257 DMA ВТ57
PINPUT 7HLDA..-.12CLK.-.6RDY.-.13RES..-19:16DRQ0:3'-.11_CS
PINOUT 10HRQ-4_MEMR 2_IOWR 1_IORD-32:35;37:40A0:7-30:26;23:21D0:7-8STB 9AEN-14_DAC2
</textarea><br />
<canvas id=Design width=300 height=400></canvas><br>
<textarea id=Model rows=6 cols=100></textarea>
<script>main();</script>
</body>