#!/usr/bin/env splrun var idx = 0; var count_nand = 0; var count_nor = 0; function makeNAND(net, id) { count_nand++; net["${id}_VDD"] = "${id}_pa S"; net["${id}_VSS"] = "${id}_nb S"; net["${id}_A"] = "${id}_pa G"; net["${id}_B"] = "${id}_pb G"; net["${id}_Y"] = "${id}_pb D"; return <:> : node ${id}_pa pmos S 1 D 1 G 1 : node ${id}_pb pmos S 1 D 1 G 1 : node ${id}_na nmos S 1 D 1 G 1 : node ${id}_nb nmos S 1 D 1 G 1 : connect ${id}_pa S ${id}_pb S : connect ${id}_pa D ${id}_pb D : connect ${id}_pa D ${id}_na D : connect ${id}_na S ${id}_nb D : connect ${id}_pa G ${id}_na G : connect ${id}_pb G ${id}_nb G ; } function makeNOR(net, id) { count_nor++; net["${id}_VDD"] = "${id}_pa S"; net["${id}_VSS"] = "${id}_nb S"; net["${id}_A"] = "${id}_pa G"; net["${id}_B"] = "${id}_pb G"; net["${id}_Y"] = "${id}_pb D"; return <:> : node ${id}_pa pmos S 1 D 1 G 1 : node ${id}_pb pmos S 1 D 1 G 1 : node ${id}_na nmos S 1 D 1 G 1 : node ${id}_nb nmos S 1 D 1 G 1 : connect ${id}_pa D ${id}_pb S : connect ${id}_pb D ${id}_na D : connect ${id}_pb D ${id}_nb D : connect ${id}_na S ${id}_nb S : connect ${id}_pa G ${id}_na G : connect ${id}_pb G ${id}_nb G ; } function makeGraph(seed, gates, primaryInputs, primaryOutputs) { srand(seed); var code = ""; var net, vdd, vss, outputs; var unusedOutpus; for (var i = 0; i < gates; i++) { var id = fmt("G%d", idx++); if (rand(2) == 0) code ~= makeNAND(net, id); else code ~= makeNOR(net, id); if (i == 0) { vdd = net["${id}_VDD"]; vss = net["${id}_VSS"]; } else { code ~= <:> : connect $vdd ${net["${id}_VDD"]} : connect $vss ${net["${id}_VSS"]} ; } var inIdx1 = rand((elementsof outputs) + 1); if (inIdx1 < elementsof outputs) { code ~= " connect ${outputs[inIdx1]} ${net["${id}_A"]}\n"; delete unusedOutpus[outputs[inIdx1]]; } else push primaryInputs, net["${id}_A"]; var inIdx2 = rand((elementsof outputs) + 1); if (inIdx2 < elementsof outputs) { code ~= " connect ${outputs[inIdx2]} ${net["${id}_B"]}\n"; delete unusedOutpus[outputs[inIdx2]]; } else push primaryInputs, net["${id}_B"]; unusedOutpus[net["${id}_Y"]] = 1; push outputs, net["${id}_Y"]; } foreach netDecl (unusedOutpus) push primaryOutputs, netDecl; return code; } function makeConnections(fromNets, toNets) { var code = ""; foreach[] toNet (toNets) { var fromNet = fromNets[rand(elementsof fromNets)]; code != " connect $fromNet $toNet\n"; } return code; } var numNodes; write(<:> : graph nand ${makeNAND(net, "nand")} : extern ${net["nand_VDD"]} : extern ${net["nand_VSS"]} : extern ${net["nand_A"]} : extern ${net["nand_B"]} : extern ${net["nand_Y"]} : endgraph : : graph nor ${makeNOR(net, "nor")} : extern ${net["nor_VDD"]} : extern ${net["nor_VSS"]} : extern ${net["nor_A"]} : extern ${net["nor_B"]} : extern ${net["nor_Y"]} : endgraph : : graph needle_1 ${makeGraph(1, 100, ports, ports)} : extern $net : endgraph : : graph needle_2 ${makeGraph(2, 200, ports, ports)} : extern $net : endgraph : : graph needle_3 ${makeGraph(3, 300, ports, ports)} : extern $net : endgraph : : graph haystack ${makeGraph(1, 100, inPorts1, outPorts1)} ${makeGraph(2, 200, inPorts2, outPorts2)} ${makeGraph(3, 300, inPorts3, outPorts3)} ${makeGraph(2, 200, inPorts4, outPorts4)} ${makeGraph(1, 100, inPorts5, outPorts5)} ${makeConnections(outPorts1, inPorts2)} ${makeConnections(outPorts2, inPorts3)} ${makeConnections(outPorts3, inPorts4)} ${makeConnections(outPorts4, inPorts5)} : endgraph : : solve nand haystack false : expect $count_nand : clearoverlap : : solve nor haystack false : expect $count_nor : clearoverlap : : solve needle_1 haystack false : expect 2 : : solve needle_2 haystack false : expect 2 : : solve needle_3 haystack false : expect 1 ); numNodes["haystack"] -= numNodes["needle_3"]; numNodes["needle_3"] -= numNodes["needle_2"]; numNodes["needle_2"] -= numNodes["needle_1"]; write(<:> : : # Needle_1: ${numNodes["needle_1"]} transistors : # Needle_2: ${numNodes["needle_2"]} transistors : # Needle_3: ${numNodes["needle_3"]} transistors : # Haystack: ${numNodes["haystack"]} transistors );