def post_visit(g, code, tmp, d_stack, expd_dels, n, visited) : # print "post_visit", n, n.prototype if core.compare_proto_to_type(n.prototype, core.ConstProto) : return None # handled elsewhere if core.compare_proto_to_type(n.prototype, core.DelayInProto) : del_in, del_out = expd_dels[n.delay] # print 1 if not del_out in visited : # print 2 slot = add_tmp_ref(tmp, [ (del_in, del_in.terms[0], 0) ]) code.append("del%i to tmp%i" % (n.nr, slot)) code.append("to del%i" % n.nr) elif core.compare_proto_to_type(n.prototype, core.DelayOutProto) : del_in, del_out = expd_dels[n.delay] if del_in in visited : slot = pop_tmp_ref(tmp, del_in, del_in.terms[0], 0) code.append("tmp%i" % slot) else : code.append("del%i" % n.nr) else : assert(n.prototype.exe_name != None) code.append(n.prototype.exe_name) #manage outputs outputs = g[n].s for out_term, out_t_nr, succs in outputs : # print "out_term, succs", out_term, succs if len(succs) == 1 : if len(n.prototype.outputs) == 1 : #XXX d_stack.append(succs[0]) d_stack.append((n, out_term, out_t_nr)) else : slot = add_tmp_ref(tmp, list(succs)) code.append("to tmp%i" % slot) pass # store on d stack, OR NO!?! (allways) possible only with single-output block elif len(succs) > 1 : if len(n.prototype.outputs) == 1 : code.append("dup") # print "post_visit, leaving on d:", succs[0] #XXX d_stack.append(succs[0]) d_stack.append((n, out_term, out_t_nr)) # print "list(succs)=", list(succs) slot = add_tmp_ref(tmp, list(succs)) #XXX including one to be taken from d, not good code.append("to tmp%i" % slot) pass # leading to multiple inputs, store in temp else : code.append("drop")# unconnected, drop
def expand_macroes(g, library, known_types, local_block_sheets, block_cache=None) : cache = block_cache_init() if block_cache is None else block_cache new_delays = {} prev_batch = set() macroes = { b for b in g if core.compare_proto_to_type(b.prototype, core.MacroProto) } while macroes != prev_batch : for n in sorted(macroes) : delays, = __expand_macro(g, library, n, known_types, cache, local_block_sheets) new_delays.update(delays) prev_batch = set(macroes) macroes = { b for b in g if core.compare_proto_to_type(b.prototype, core.MacroProto) } if macroes : raise Exception("failed to {0} expand macroes".format(len(macroes))) return (new_delays, )
def __expand_macro(g, library, n, known_types, cache, local_block_sheets) : name = n.prototype.exe_name full_name = n.prototype.library + "." + name # print here(), full_name sheet = None if n.prototype.library == "<local>" : # print here(), full_name sheet_name = "@macro:" + name if sheet_name in local_block_sheets : sheet = core.clone_sheet(local_block_sheets[sheet_name][1], library) else : sheet = core.load_library_sheet(library, full_name, "@macro:" + name) if sheet is None : raise Exception("failed to expand macro '" + full_name + "'") offset = reduce(max, (b.nr for b in g if core.compare_proto_to_type(b.prototype, core.DelayInProto)), 0)#TODO gm, delays = make_dag(sheet, None, known_types, do_join_taps=False, delay_numbering_start=offset+1) #TODO # print here(), full_name, full_name in cache # if full_name in cache : # block = cache[full_name] # else : # block = __instantiate_macro(library, full_name) # cache[full_name] = block inputs = { b.value[0] : (b, s[0][2]) for b, (_, s) in gm.items() if core.compare_proto_to_type(b.prototype, core.InputProto) } outputs = { b.value[0] : (b, p[0][2]) for b, (p, _) in gm.items() if core.compare_proto_to_type(b.prototype, core.OutputProto) } for io_blocks in (inputs, outputs) : for io, _ in io_blocks.values() : remove_block(gm, io) p, s = g[n] #XXX to handle variadic terms map p -> inputs map_in = { (it, it_nr) : tuple((b, t, nr) for b, t, nr in inputs[it.name][1]) for it, it_nr, _ in p } map_out = { (ot, ot_nr) : tuple((b, t, nr) for b, t, nr in outputs[ot.name][1]) for ot, ot_nr, _ in s } remove_block_and_patch(g, n, gm, map_in, map_out) return (delays, )
def get_term_presentation_text(self, t, nr) : term_label = t.name if core.compare_proto_to_type(self.prototype, core.ConstProto) : term_label = ""#str(self.model.value) if t.variadic : #XXX nr != None term_label += str(self.get_term_index(t, nr)) return term_label
def __infer_types_pre_dive(g, delays, types, known_types, n, nt, nt_nr, m, mt, mt_nr, visited) : mt_type_name = mt.type_name # print(here(), n, nt, nt_nr, "<-", m, mt, mt_nr, "type:", mt_type_name) if mt_type_name == core.TYPE_INFERRED : if core.compare_proto_to_type(m.prototype, core.DelayOutProto) : value_type, _ = parse_literal(delays[m], known_types=known_types) mt_type_name = types[m, mt, mt_nr] = value_type elif core.compare_proto_to_type(m.prototype, core.ConstProto) : value_type, _ = parse_literal(m.value[0], known_types=known_types) mt_type_name = types[m, mt, mt_nr] = value_type else : types[m, mt, mt_nr] = mt_type_name = infer_block_type(m, g[m].p, types, known_types) if core.compare_proto_to_type(m.prototype, core.DelayOutProto) : pass if nt.type_name == core.TYPE_INFERRED : types[n, nt, nt_nr] = mt_type_name
def __expand_delays(blocks, conns, delay_numbering_start) : delays = frozenset(b for b in blocks if core.compare_proto_to_type(b.prototype, core.DelayProto, core.InitDelayProto)) # delays = { b for b in blocks if core.compare_proto_to_type(b.prototype, core.DelayProto) } # print here(), delays expd = dict(__expddel(delay, delay_numbering_start + nr) for delay, nr in zip(delays, count())) # print here(), expd # def mkvert(src, io) : # b, t = src # block, term = ( ( expd[b][io], expd[b][io].terms[0] ) # if core.compare_proto_to_type(b.prototype, core.DelayProto) # else (b, t) ) # return (block, ) + t_unpack(term) conns2 = {} for s, dests in conns.items() : k = __mkvert(s, expd) v = [ __mkvert(d, expd) for d in dests ] # print here(), "s:", s, "dests:", dests, #"k:", k, "v:", v conns2[k] = v # sys.exit(0) # conns2 = { __mkvert(s, 1, expd) : [ __mkvert(d, 0, expd) for d in dests ] for s, dests in conns.items() } return list((set(blocks)-delays).union(chain(*expd.values()))), conns2, expd
def get_taps(g) : """ return { tap_name : tap, ... } """ tap_list = [ b for b, (p, s) in g.items() if core.compare_proto_to_type(b.prototype, core.TapProto) ] taps = { b.value : b for b in tap_list } assert(len(tap_list)==len(taps)) return taps
def get_tap_ends(g) : """ return { tap_name : [ tap_end1, ...], ... } """ tap_ends_list = { b for b in g.keys() if core.compare_proto_to_type(b.prototype, core.TapEndProto) } tap_ends = groupby_to_dict(tap_ends_list, lambda b: b.value, lambda b: b, lambda x: list(x)) assert( len(tap_ends_list) == sum([len(v) for v in tap_ends.values()]) ) return tap_ends
def extract_pipes(g, known_types, g_protos, pipe_replacement) : pipes = { n for n in g if core.compare_proto_to_type(n.prototype, core.PipeProto) } for n in pipes : pipe_name = block_value_by_name(n, "Name") pipe_default = block_value_by_name(n, "Default") pipe_type, v = parse_literal(pipe_default, known_types=known_types, variables={}) gw_proto, gr_proto = g_protos[pipe_type] pipe_replacement[pipe_name] = (pipe_type, pipe_default, gw_proto, gr_proto)
def __expddel(d, nr) : i = dfs.BlockModel(core.DelayInProto(), None) # print here(), d, nr if core.compare_proto_to_type(d.prototype, core.InitDelayProto) : # print here() o = dfs.BlockModel(core.InitDelayOutProto(), None) else : o = dfs.BlockModel(core.DelayOutProto(), None) i.nr = o.nr = nr i.delay = o.delay = d return d, (i, o)
def replace_pipes(g, g_protos, pipe_replacement) : pipe_ends = { n : block_value_by_name(n, "Name") for n in g if core.compare_proto_to_type(n.prototype, core.PipeEndProto) } unmatched = [ pe for pe in pipe_ends if not (block_value_by_name(pe, "Name") in pipe_replacement) ] if unmatched : raise Exception("unmatched pipes found! {0}".format(str(unmatched))) pipes = { n for n in g if core.compare_proto_to_type(n.prototype, core.PipeProto) } for n in pipes : pipe_name = block_value_by_name(n, "Name") pipe_type, pipe_default, gw_proto, gr_proto = pipe_replacement[pipe_name] gw_proto, gr_proto = g_protos[pipe_type] m = dfs.BlockModel(gw_proto, "itentionally left blank") m.value = (pipe_name, ) replace_block(g, n, m) for pipe_end, pipe_name in pipe_ends.items() : pipe_type, pipe_default, gw_proto, gr_proto = pipe_replacement[pipe_name] m = dfs.BlockModel(gr_proto, "itentionally left blank") m.value = (pipe_name, ) replace_block(g, pipe_end, m)
def __implement(g, n, tmp_args, args, outs, code) : """ return code to perform block n """ stmt = None if n.prototype.type_name in __OPS : assert(len(args) >= 2 or n.prototype.type_name in ("not", "abs")) assert(len([t for t in n.terms if t.direction==core.OUTPUT_TERM]) == 1) stmt = __OPS[n.prototype.type_name](n, tuple("({0})".format(a) for _, a in args)) elif core.compare_proto_to_type(n.prototype, core.FunctionCallProto) : func_name = block_value_by_name(n, "Name") assert(func_name) stmt = func_name + "(" + ", ".join(tuple(a for _, a in (args + outs))) + ")" elif core.compare_proto_to_type(n.prototype, core.GlobalReadProto) : assert(len(args)==0) pipe_name = block_value_by_name(n, "Name") assert(pipe_name) stmt = pipe_name elif core.compare_proto_to_type(n.prototype, core.GlobalWriteProto) : assert(len(args)==1) pipe_name = block_value_by_name(n, "Name") assert(pipe_name) stmt = "{0} = {1}".format(pipe_name, args[0][1]) elif core.compare_proto_to_type(n.prototype, core.MuxProto) : assert(len(args)==3) stmt = "({0} ? {2} : {1})".format(*tuple(a for _, a in args))#XXX cast sometimes needed!!! elif core.compare_proto_to_type(n.prototype, core.TypecastProto) : assert(len(args)==1) out = tuple(t for t in n.terms if t.direction==core.OUTPUT_TERM) assert(len(out)==1) stmt = "({0})({1})".format(out[0].type_name, args[0][1]) else : stmt = __make_call(n, args, outs, tmp_args, code) # assert(n.prototype.exe_name != None) # return n.prototype.exe_name + "(" + ", ".join(args + outs) + ")" assert(not stmt is None) return stmt
def make_dag(model, meta, known_types, do_join_taps=True, delay_numbering_start=0) : conns0 = { k : v for k, v in model.connections.items() if v } model_blocks = tuple(b for b in model.blocks if not core.compare_proto_to_type(b.prototype, core.TextAreaProto)) blocks, conns1, delays = __expand_delays(model_blocks, conns0, delay_numbering_start) conns_rev = reverse_dict_of_lists(conns1, lambda values: list(set(values))) graph = { b : adjs_t( [ (t, n, conns_rev[(b, t, n)] if (b, t, n) in conns_rev else []) for t, n in in_terms(b) ], [ (t, n, conns1[(b, t, n)] if (b, t, n) in conns1 else []) for t, n in out_terms(b) ]) for b in blocks } is_sane = __dag_sanity_check(graph, stop_on_first=False) if not is_sane : raise Exception(here() + ": produced graph is insane") __expand_joints_new(graph) if do_join_taps : join_taps(graph) return graph, delays
def post_dive(g, code, tmp, d_stack, n, nt, nt_nr, m, mt, mt_nr, visited) : # print "post_dive:", n, nt, "<-", m, mt # assert(n in visited) # assert(m in visited) # print "d_stack=", d_stack, "(n, nt)=", (n, nt) if core.compare_proto_to_type(m.prototype, core.ConstProto) : assert(m.value != None) assert(len(m.value) == 1) code.append(str(m.value[0])) # print "post_dive:", n, nt, "<-", m, mt, "code:", str(m.value) elif (m, mt, mt_nr) in d_stack : #XXX or (n, nt) == d_stack[-1] ??!?!? nope, it is equal d_stack.remove((m, mt, mt_nr)) pop_tmp_ref(tmp, n, nt, nt_nr) # print "post_dive:", n, nt, "<-", m, mt, "code:", "nop, d stack" else : slot = pop_tmp_ref(tmp, n, nt, nt_nr) if slot != None: code.append("tmp%i" % slot) # print "post_dive:", n, nt, "<-", m, mt, "code:", "tmp%i" % slot else : raise Exception("holy shit!")
def __mkvert(src, expd) : b, t0 = src t, _ = t_unpack(t0) if core.compare_proto_to_type(b.prototype, core.DelayProto, core.InitDelayProto) : block = expd[b][ 1 if t.name in ("y", "init") else 0 ] term, = get_terms_flattened(block, direction=t.direction) # if core.compare_proto_to_type(b.prototype, core.DelayProto) : # io = 1 if t.direction == core.OUTPUT_TERM else 0 # block = expd[b][io] # term, = block.terms # elif core.compare_proto_to_type(b.prototype, core.InitDelayProto) : # io = 1 if t.name in ("y", "init") else 0 # block = expd[b][io] # print here(), src, block, tuple(get_terms_flattened(block, direction=t.direction)), io # term, = get_terms_flattened(block, direction=t.direction) else : block, term = src result_t, result_t_nr = t_unpack(term) assert(t.direction==result_t.direction) return (block, result_t, result_t_nr)
def __post_visit(g, code, tmp, tmp_args, subtrees, expd_dels, types, known_types, dummies, state_var_prefix, pipe_vars, libs_used, evaluated, n, visited) : # print "__post_visit:", n.to_string() if core.compare_proto_to_type(n.prototype, core.ConstProto) : return None # handled elsewhere if n.prototype.library : libs_used.add(n.prototype.library) inputs_all, outputs_all = g[n] inputs = [ (t, nr, ngh) for t, nr, ngh in inputs_all if not t.virtual ] outputs = [ (t, nr, ngh) for t, nr, ngh in outputs_all if not t.virtual ] args = [] outs = [] # print here(), n, tmp, subtrees # print here(), n, outputs expr_slot_type = None for out_term, out_t_nr, succs in outputs : # if out_term.virtual : # continue if out_term.type_name == core.TYPE_INFERRED : term_type = types[n, out_term, out_t_nr] else : term_type = out_term.type_name # print "out_term, out_t_nr, succs =", n, out_term, out_term.type_name, out_t_nr, succs if len(succs) > 1 or (len(outputs) > 1 and len(succs) == 1): # print "adding temps:", succs expr_slot_type = term_type expr_slot = add_tmp_ref(tmp, succs, slot_type=term_type) #TODO if all succs have same type different from out_term, cast now and store as new type #if storage permits, however if len(outputs) > 1 : outs.append(((out_term, out_t_nr), "&{}_tmp{}".format(expr_slot_type, expr_slot))) elif len(succs) == 1 and len(outputs) == 1 : # print here(), "passing by", n pass else : dummies.add(term_type) outs.append(((out_term, out_t_nr), "&{}_dummy".format(term_type))) for in_term, in_t_nr, preds in inputs : # print here(), n, preds assert(len(preds)==1) # if out_term.virtual : # continue ((m, m_t, m_t_nr), ) = preds # print "\tgathering:", m, m_t, m_t_nr, "for", (n, in_term, in_t_nr), "subtrees:", subtrees, "tmp:", tmp if core.compare_proto_to_type(m.prototype, core.ConstProto) : assert(m.value != None) assert(len(m.value) == 1) args.append(((in_term, in_t_nr), str(m.value[0]))) elif (n, in_term, in_t_nr) in subtrees : args.append(((in_term, in_t_nr), subtrees.pop((n, in_term, in_t_nr)))) else : slot_type, slot = pop_tmp_ref(tmp, n, in_term, in_t_nr) if slot != None: args.append(((in_term, in_t_nr), "{0}_tmp{1}".format(slot_type, slot))) else : assert(False) if core.compare_proto_to_type(n.prototype, core.DelayInProto) : del_in, del_out = expd_dels[n.delay] assert(n==del_in) # is_initdel = core.compare_proto_to_type(del_out.prototype, core.InitDelayOutProto) if not del_out in evaluated :# or is_initdel : # print here(), del_in.terms del_type = types[del_out, del_out.terms[0], 0] slot = add_tmp_ref(tmp, [ (del_in, del_in.terms[0], 0) ], slot_type=del_type) if core.compare_proto_to_type(del_out.prototype, core.InitDelayOutProto) :# is_initdel : # print here(), args assert(len(args)==1 and len(outs)==0) __get_initdel_value(code, n, state_var_prefix, del_type, slot, args[0][1]) else : code.append("{0}_tmp{1} = {2}del{3};".format(del_type, slot, state_var_prefix, n.nr)) expr = "{0}del{1}={2}".format(state_var_prefix, n.nr, args[0][1]) elif core.compare_proto_to_type(n.prototype, core.DelayOutProto, core.InitDelayOutProto) : del_in, del_out = expd_dels[n.delay] assert(n==del_out) if del_in in evaluated : #visited : slot_type, slot = pop_tmp_ref(tmp, del_in, del_in.terms[0], 0) expr = "{0}_tmp{1}".format(slot_type, slot) else : if core.compare_proto_to_type(n.prototype, core.InitDelayOutProto) : assert(len(args)==1 and len(outs)==0) del_type = types[del_out, del_out.terms[0], 0] slot = add_tmp_ref(tmp, [ (del_in, del_in.terms[0], 0) ], slot_type=del_type) __get_initdel_value(code, n, state_var_prefix, del_type, slot, args[0][1]) slot_type, slot = pop_tmp_ref(tmp, del_in, del_in.terms[0], 0) expr = "{0}_tmp{1}".format(slot_type, slot) else : expr = "{0}del{1}".format(state_var_prefix, n.nr) else : expr = __implement(g, n, tmp_args, args, outs, code)#, types, known_types, pipe_vars) is_expr = len(outputs) == 1 and len(outputs[0][2]) == 1 if is_expr : ((out_term, out_t_nr, succs), ) = outputs subtrees[succs[0]] = expr assert(len(outputs)==1 and len(outputs[0][2])==1) subtrees[outputs[0][2][0]] = expr else : if len(outputs) == 0 : code.append(expr + ";") elif len(outputs) == 1 : # (out_term,) = [ trm for trm in n.terms if trm.direction == core.OUTPUT_TERM ] # term_type = types[ n, out_term, 0 ] # slot = add_tmp_ref(tmp, outputs[0][2], slot_type=term_type) # print here(), n, out_term, term_type, "slot=", slot # pprint(tmp) if expr_slot_type is None : code.append("(void){};".format(expr)) else : code.append("{0}_tmp{1} = {2};".format(expr_slot_type, expr_slot, expr)) else : code.append(expr + ";") evaluated[n] = True
def __expand_joints_new(g) : for j in [ b for b in g if core.compare_proto_to_type(b.prototype, core.JointProto) ] : __cut_joint_alt(g, j)
def __inferr_types_dft_roots_sorter(g, roots) : return sorted(dft_alt_roots_sorter(g, roots), key=lambda n: 0 if core.compare_proto_to_type(n.prototype, core.InitDelayOutProto) else 1)