def connect_invocation_indirect_writes( graph: GraphInstance, inst: SystemInstance, instances_by_set: Dict[Set, List[DeviceInstance]], gi: DeviceInstance, ctxt: InvocationContext): graph_type = graph.graph_type invocation = ctxt.stat.id write_recv_counts = collections.Counter() for s in ctxt.get_all_involved_sets(): for di in instances_by_set[s]: write_recv_counts[ di] += 1 # Everything has an execute, even those not on the iter set for (index, arg) in ctxt.indirect_writes: dst_type = graph_type.device_types["set_{}".format(arg.to_set.id)] dst_pin = dst_type.pins["{invocation}_arg{index}_write_recv".format( invocation=invocation, index=index)] src_type = graph_type.device_types["set_{}".format(arg.iter_set.id)] src_pin_name = "{invocation}_arg{index}_write_send".format( invocation=invocation, index=index) src_pin = src_type.pins[src_pin_name] iter_instances = instances_by_set[arg.iter_set] to_instances = instances_by_set[arg.to_set] mapping = inst.maps[arg.map] if arg.index >= 0: for (src_index, src_instance) in enumerate(iter_instances): dst_index = mapping[src_index][arg.index] dst_instance = to_instances[dst_index] write_recv_counts[dst_instance] += 1 graph.create_edge_instance(dst_instance, dst_pin, src_instance, src_pin) else: for (src_index, src_instance) in enumerate(iter_instances): for ai in range(arg.map.arity): dst_index = mapping[src_index][ai] dst_instance = to_instances[dst_index] write_recv_counts[dst_instance] += 1 graph.create_edge_instance(dst_instance, dst_pin, src_instance, src_pin, {"index": ai}) write_recv_total_name = "{invocation}_write_recv_total".format( invocation=invocation) for (di, count) in write_recv_counts.items(): di.set_property(write_recv_total_name, count)
def connect_invocation_indirect_reads( graph: GraphInstance, inst: SystemInstance, instances_by_set: Dict[Set, List[DeviceInstance]], gi: DeviceInstance, ctxt: InvocationContext): graph_type = graph.graph_type invocation = ctxt.stat.id for (index, arg) in ctxt.indirect_reads: dst_type = graph_type.device_types["set_{}".format(arg.iter_set.id)] dst_pin = dst_type.pins["{invocation}_arg{index}_read_recv".format( invocation=invocation, index=index)] src_type = graph_type.device_types["set_{}".format(arg.to_set.id)] src_pin_name = "{invocation}_dat_{dat}_read_send".format( invocation=invocation, dat=arg.dat.id) if src_pin_name not in src_type.pins: raise RuntimeError( "Couldn't find pin {} in {}. Pins are {}".format( src_pin_name, src_type.id, ",".join(src_type.pins))) src_pin = src_type.pins[src_pin_name] iter_instances = instances_by_set[arg.iter_set] to_instances = instances_by_set[arg.to_set] mapping = inst.maps[arg.map] if arg.index >= 0: for (dst_index, dst_instance) in enumerate(iter_instances): src_index = mapping[dst_index][arg.index] src_instance = to_instances[src_index] graph.create_edge_instance(dst_instance, dst_pin, src_instance, src_pin) else: assert -arg.index == arg.map.arity for (dst_index, dst_instance) in enumerate(iter_instances): for index in range(arg.map.arity): src_index = mapping[dst_index][index] src_instance = to_instances[src_index] graph.create_edge_instance(dst_instance, dst_pin, src_instance, src_pin, {"index": index})
def build_graph(globalDeviceType: str, spec: SystemSpecification, inst: SystemInstance, code: Statement): graphTypeBuilder = sync_compiler(spec, code) graphType = graphTypeBuilder.build() graph = GraphInstance("op2", graphType) for g in spec.globals.values(): if isinstance(g, MutableGlobal): graph.set_property("init_global_{}".format(g.id), inst.globals[g].tolist()) elif isinstance(g, ConstGlobal): graph.set_property("global_{}".format(g.id), inst.globals[g].tolist()) else: assert "Unknown global type" gi = graph.create_device_instance("global", globalDeviceType) instancesBySet = {} # type: Dict[Set,List[DeviceInstance]] instancesByName = {} # type: Dict[str,DeviceInstance] for set in spec.sets.values(): instances = instancesBySet.setdefault(set, []) dt = graphType.device_types["set_{}".format(set.id)] for i in range(inst.sets[set]): name = "{}_{}".format(set.id, i) di = graph.create_device_instance(name, dt) instances.append(di) instancesByName[name] = di for (dat, vals) in inst.dats.items(): init_dat_name = "init_dat_{}".format(dat.id) for (index, di) in enumerate(instancesBySet[dat.set]): sys.stderr.write("{}, {}, {}\n".format(dat.set.id, dat.id, index)) di.set_property(init_dat_name, vals[index].tolist()) kernels = find_kernels_in_code(code) for (i, stat) in enumerate(kernels): ctxt = InvocationContext(spec, stat) connect_invocation(graph, inst, instancesBySet, gi, ctxt) return graph
def connect_invocation(graph: GraphInstance, inst: SystemInstance, instances_by_set: Dict[Set, List[DeviceInstance]], gi: DeviceInstance, ctxt: InvocationContext): graph_type = graph.graph_type invocation = ctxt.stat.id all_involved = ctxt.get_all_involved_sets() total_responding_devices = 0 for s in all_involved: begin = "{}_begin".format(invocation) end = "{}_end".format(invocation) for di in instances_by_set[s]: graph.create_edge_instance(di, begin, gi, begin) graph.create_edge_instance(gi, end, di, end) total_responding_devices += 1 graph.set_property( "{invocation}_total_responding_devices".format(invocation=invocation), total_responding_devices) connect_invocation_indirect_reads(graph, inst, instances_by_set, gi, ctxt) connect_invocation_indirect_writes(graph, inst, instances_by_set, gi, ctxt)
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)
# d=int(sys.argv[1]) # if len(sys.argv)>2: # b=int(sys.argv[2]) # if len(sys.argv)>3: # maxTicks=int(sys.argv[3]) graphType = graphTypes["circuit_gates"] universal2Gate = graphType.device_types["universal2"] inputTerminalGate = graphType.device_types["input_terminal"] outputTerminalGate = graphType.device_types["output_terminal"] exitNode = graphType.device_types["exit_node"] instName = "full_adder_1bit" properties = {"max_ticks": maxTicks} res = GraphInstance(instName, graphType, None) usingCircuit = { "name": "1-bit full adder Cin, A, B -> Sum, Cout", "in": [1, 2, 3], "out": [5, 11], "gates": [{ "id": 4, "type": "XOR", "in": [2, 3] }, { "id": 5, "type": "XOR", "in": [1, 4] }, {
# if len(sys.argv)>1: # d=int(sys.argv[1]) # if len(sys.argv)>2: # b=int(sys.argv[2]) # if len(sys.argv)>3: # maxTicks=int(sys.argv[3]) graphType = graphTypes["circuit_gates"] properties = {"max_ticks": maxTicks} for d in designs_sexp: designName = get_sexp_name(d) designContents = get_sexp_list_contents(d) cellRefs = get_sexp_list(designContents, "cellRef") res = GraphInstance(designName, graphType, None) for cellRef in cellRefs: cellRefName = get_sexp_name(cellRef) libRef = get_sexp_list_content(cellRef) libRefName = get_sexp_name(libRef) cell = intLibs[libRefName][cellRefName] cell.instantiate(res=res, graphTypes=graphTypes, externalLibs=extLibs) if args.output_file == "STDOUT": save_dst = sys.stdout else: save_dst = args.output_file save_graph(res, save_dst) #print(extLibs)