Показать сообщение отдельно
  #196 (permalink)  
Старый 08.07.2022, 00:02
Аватар для Alikberov
Кандидат Javascript-наук
Отправить личное сообщение для Alikberov Посмотреть профиль Найти все сообщения от Alikberov
 
Регистрация: 16.08.2018
Сообщений: 109

Интерактивный генератор УГО микросхем
<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>

Последний раз редактировалось Alikberov, 20.10.2023 в 12:22. Причина: JSFiddle не работает? Немного "облаков" здесь
Ответить с цитированием