def instantiate(self, res: GraphInstance, graphTypes, externalLibs): """ externalLibs={ "libname": { "name": Cell1, "name2": Cell2 } } """ # gates graphType = graphTypes["circuit_gates"] inputTerminalGate = graphType.device_types["input_terminal"] outputTerminalGate = graphType.device_types["output_terminal"] ioOracle = graphType.device_types["io_oracle"] # exit is controlled by global `max_ticks` exitNode = graphType.device_types["exit_node"] graphInstDict = {} # io terminals inTermInsts = [] outTermInsts = [] def get_gate_type(libRef, cellRef): cell = externalLibs[libRef][cellRef] return cell.orignal_name def find_gt_gate(gateType, device_types=graphType.device_types): return device_types[gateMappings[gateType]] def get_input_ports(cell): return [ p for (p, dirc) in cell.ports.items() if dirc == "INPUT" ] def get_output_ports(cell): return [ p for (p, dirc) in cell.ports.items() if dirc == "OUTPUT" ] def get_net_terminals(cell, direction: str, nets, eLibs, graphInstDict): """ return terminal device(s) and its port port must match port definition in graph schema INPUT for a Cell is drain, but it is src for a port """ srcTerms = [] for term in nets: if term.instanceRef: inst = cell.instances[term.instanceRef] # the base gate gate = eLibs[inst.libRef][inst.cellRef] if gate.ports[term.portRef] != direction: srcTerms.append( (graphInstDict[term.instanceRef], term.portRef) ) else: if cell.ports[term.portRef] == direction: # input terminal has only one output pin # output terminal has only one receive pin pinName = "out" if direction == "INPUT" else "receive" srcTerms.append( (graphInstDict[term.portRef], pinName) ) if direction == "INPUT": assert(len(srcTerms) == 1, "There can only be one source terminal in the net", srcTerms) return srcTerms[0] else: return srcTerms # construct device instance for (instId, inst) in self.instances.items(): gType = get_gate_type(inst.libRef, inst.cellRef) node = DeviceInstance( parent=res, id="{0}_{1}".format(gType, instId), device_type=find_gt_gate(gType), ) res.add_device_instance(node) graphInstDict[instId] = node # construct input terminals inTerms = get_input_ports(self) inTermTid = 0 for inPin in inTerms: gid = inPin node = DeviceInstance( parent=res, id="{0}_{1}_{2}".format(self.name, "it", gid), device_type=inputTerminalGate, properties={"tid": inTermTid} ) inTermTid += 1 res.add_device_instance(node) graphInstDict[gid] = node inTermInsts.append(node) # construct output terminals outTerms = get_output_ports(self) outTermTid = 0 for outPin in outTerms: gid = outPin node = DeviceInstance( parent=res, id="{0}_{1}_{2}".format(self.name, "ot", gid), device_type=outputTerminalGate, properties={"tid": outTermTid} ) outTermTid += 1 res.add_device_instance(node) graphInstDict[gid] = node outTermInsts.append(node) # construct edge instances for (_, edges) in self.nets.items(): # find the only source (srcDev, srcPin) = get_net_terminals( self, "INPUT", edges, externalLibs, graphInstDict) # find drains drains = get_net_terminals( self, "OUTPUT", edges, externalLibs, graphInstDict) for (dstDev, dstPin) in drains: # except KeyError: # srcDev = None # srcPin = None edgeInst = EdgeInstance( parent=res, dst_device=dstDev, dst_pin=dstPin, src_device=srcDev, src_pin=srcPin) res.add_edge_instance(edgeInst) # construct io_oracle ioOracleInst = DeviceInstance( parent=res, id="{0}_io_oracle".format(self.name), device_type=ioOracle, properties={"no_inputs": len(inTermInsts), "no_outputs": len(outTermInsts), "combinations": pow(2, len(inTermInsts))-1, "full_ot_mask": pow(2, len(outTermInsts))-1 } ) res.add_device_instance(ioOracleInst) for iTerm in inTermInsts: edgeInst = EdgeInstance( parent=res, dst_device=iTerm, dst_pin="io_oracle_receive", src_device=ioOracleInst, src_pin="it_feed" ) res.add_edge_instance(edgeInst) for oTerm in outTermInsts: edgeInst = EdgeInstance( parent=res, dst_device=ioOracleInst, dst_pin="ot_receive", src_device=oTerm, src_pin="out" ) res.add_edge_instance(edgeInst)
for gate in usingCircuit["gates"]: gid = gate["id"] gType = gate["type"] for idx, inPin in enumerate(gate["in"]): # try: srcDev = graphInstDict[inPin] srcPin = "out" # except KeyError: # srcDev = None # srcPin = None edgeInst = EdgeInstance(parent=res, dst_device=graphInstDict[gid], dst_pin="in{}".format(idx), src_device=srcDev, src_pin=srcPin) res.add_edge_instance(edgeInst) # connect output terminals for srcGate in usingCircuit["out"]: destGate = str(srcGate) + "ot" # try: destDev = graphInstDict[destGate] destPin = "receive" srcDev = graphInstDict[srcGate] srcPin = "out" # except KeyError: # srcDev = None # srcPin = None edgeInst = EdgeInstance(parent=res, dst_device=destDev, dst_pin=destPin,