def bench_to_circuit(netlist, name): """ Creates a new Circuit from a netlist string. Parameters ---------- netlist: str netlist code. name: str the module name. Returns ------- Circuit the parsed circuit. """ # create circuit c = Circuit(name=name) # get inputs in_regex = r"(?:INPUT|input)\s*\(\s*([a-zA-Z][a-zA-Z\d_]*)\s*\)" for net_str in re.findall(in_regex, netlist, re.DOTALL): nets = net_str.replace(" ", "").replace("\n", "").replace("\t", "").split(",") for n in nets: c.add(n, "input") # handle gates regex = r"([a-zA-Z][a-zA-Z\d_]*)\s*=\s*(BUF|NOT|OR|NOR|AND|NAND|XOR|XNOR|buf|not|or|nor|and|nand|not|xor|xnor)\(([^\)]+)\)" for net, gate, input_str in re.findall(regex, netlist): # parse all nets inputs = (input_str.replace(" ", "").replace("\n", "").replace("\t", "").split(",")) c.add(net, gate.lower(), fanin=inputs) # get outputs in_regex = r"(?:OUTPUT|output)\s*\(\s*([a-zA-Z][a-zA-Z\d_]*)\s*\)" for net_str in re.findall(in_regex, netlist, re.DOTALL): nets = net_str.replace(" ", "").replace("\n", "").replace("\t", "").split(",") for n in nets: driver = c.uid(f"{n}_driver") c.relabel({n: driver}) c.add(n, "output", fanin=driver) return c
def circuit_to_verilog(c): """ Generates a str of Verilog code from a `CircuitGraph`. Parameters ---------- c: Circuit the circuit to turn into Verilog. Returns ------- str Verilog code. """ c = Circuit(graph=c.graph.copy(), name=c.name, blackboxes=c.blackboxes.copy()) # sanitize escaped nets for node in c.nodes(): if node.startswith("\\"): c.relabel({node: node + " "}) inputs = list(c.inputs()) outputs = list(c.outputs()) insts = [] wires = [] # remove outputs drivers driver_mapping = dict() for output in outputs: if len(c.fanin(output)) > 1: raise ValueError(f"Output {output} has multiple drivers.") elif len(c.fanin(output)) == 1: driver = c.fanin(output).pop() if c.type(driver) in ["input", "1", "0"]: driver = c.add(f"{output}_driver", type="buf", fanin=driver, uid=True) driver_mapping[driver] = output c.remove(c.outputs()) c.relabel(driver_mapping) # blackboxes output_map = {} for name, bb in c.blackboxes.items(): io = [] for n in bb.inputs(): driver = c.fanin(f"{name}.{n}").pop() io += [f".{n}({driver})"] for n in bb.outputs(): w = c.uid(f"{name}_{n}_load") wires.append(w) output_map[f"{name}.{n}"] = w io += [f".{n}({w})"] io_def = ", ".join(io) insts.append(f"{bb.name} {name} ({io_def})") # gates for n in c.nodes(): if c.type(n) in [ "xor", "xnor", "buf", "not", "nor", "or", "and", "nand" ]: fanin = [ output_map[f] if f in output_map else f for f in c.fanin(n) ] fanin = ", ".join(fanin) insts.append(f"{c.type(n)} g_{len(insts)} " f"({n}, {fanin})") wires.append(n) elif c.type(n) in ["0", "1"]: insts.append(f"assign {n} = 1'b{c.type(n)}") wires.append(n) elif c.type(n) in ["input", "output", "bb_input", "bb_output"]: pass else: raise ValueError(f"unknown gate type: {c.type(n)}") verilog = f"module {c.name} (" verilog += ", ".join(inputs + outputs) verilog += ");\n" verilog += "".join(f" input {inp};\n" for inp in inputs) verilog += "\n" verilog += "".join(f" output {out};\n" for out in outputs) verilog += "\n" verilog += "".join(f" wire {wire};\n" for wire in wires) verilog += "\n" verilog += "".join(f" {inst};\n" for inst in insts) verilog += "endmodule\n" return verilog