def generate_vadp_fragment_for_path(dev,route_block_instances,conn_assign): def get_route_input(blk): name = blk.inputs.field_names()[0] return blk.inputs[name] def get_route_output(blk): name = blk.outputs.field_names()[0] return blk.outputs[name] vadp_config_stmts, path = use_route_blocks(dev, \ route_block_instances, \ conn_assign) for stmt in vadp_config_stmts: yield stmt for idx in range(0,len(path)-1): src_tuple = path[idx] dest_tuple = path[idx+1] assert(not devlib.Layout.is_pattern(src_tuple[1])) assert(not devlib.Layout.is_pattern(dest_tuple[1])) srcblk = dev.get_block(src_tuple[0]) src = vadplib.PortVar(srcblk, \ devlib.Location(src_tuple[1]), \ srcblk.outputs[src_tuple[2]] \ if len(src_tuple) == 3 else \ get_route_output(srcblk) ) destblk = dev.get_block(dest_tuple[0]) dest = vadplib.PortVar(destblk, \ devlib.Location(dest_tuple[1]), \ destblk.inputs[dest_tuple[2]] \ if len(dest_tuple) == 3 else \ get_route_input(destblk) ) yield vadplib.VADPConn(src,dest)
def use_route_blocks(dev,used_route_blocks,conn_assign): path = conn_assign.path vadpstmts = [] if len(path) <= 2: return vadpstmts,list(path) new_path = list(path) for idx,(route_block,route_inst_pattern) in enumerate(path[1:-1]): blk = dev.get_block(route_block) assert(len(blk.modes) == 1) assert(len(blk.state) == 0) assert(len(blk.data) == 0) # get first compatible instance that has not been used yet try: inst = next(inst for inst in dev.layout.instances(route_block) \ if not devlib.Layout \ .intersection(inst,route_inst_pattern) is None and \ (route_block,inst) not in used_route_blocks ) new_path[1+idx]= (route_block,inst) used_route_blocks.append((route_block,inst)) target_port = vadplib.PortVar(blk,devlib.Location(inst)) stmt = vadplib.VADPConfig(target_port,blk.modes) stmt.target.ident = devlib.Location(inst) vadpstmts.append(stmt) except StopIteration as e: raise Exception("no instances for route block <%s>" % route_block) return vadpstmts,new_path
def create_vadp_frag(hierarchy, input_var, parent_vadp, instance_map={}): def fresh_ident(block): if not block.name in instance_map: instance_map[block.name] = 0 inst = instance_map[block.name] instance_map[block.name] += 1 return inst if len(hierarchy) == 0: return [] vadp = [] n_children = len(hierarchy[1]) if len(hierarchy) > 1 else 0 stems = [] for frag in hierarchy[0]: inst = fresh_ident(frag['block']) targ = vadplib.PortVar(frag['block'], inst) vadp.append(vadplib.VADPConfig(targ, frag['modes'])) inp_port = targ.make_port_var(list(frag['block'].inputs)[0]) for port, expr in frag['exprs'].items(): out_port_var = targ.make_port_var(frag['block'].outputs[port]) vadp.append(vadplib.VADPSource(out_port_var, expr)) # inject connection found_source = False for idx, stmt in enumerate(parent_vadp): if isinstance(stmt,vadplib.VADPSource) \ and stmt.dsexpr.op == oplib.OpType.VAR \ and stmt.dsexpr.name == input_var: vadp.append(vadplib.VADPConn(stmt.target, inp_port)) parent_vadp.pop(idx) found_source = True break if not found_source: vadp.append(vadplib.VADPSink(inp_port, genoplib.Var(input_var))) enclosing_vadp = list(vadp) + list(parent_vadp) if len(hierarchy) > 1: vadp += create_vadp_frag(hierarchy[1:], input_var, enclosing_vadp, instance_map) # at most one sink statement sources = list( filter(lambda vst: isinstance(vst, vadplib.VADPSource), vadp)) other_stmts = list( filter(lambda vst: not isinstance(vst, vadplib.VADPSource), vadp)) for st in vadp: if isinstance(st, vadplib.VADPConn): sources = list(filter(lambda src: st.source != src.target, sources)) vadp = sources + other_stmts n_sinks = len( list(filter(lambda vst: isinstance(vst, vadplib.VADPSink), vadp))) assert (n_sinks <= 1) return vadp
def derive_tableau_from_port_rel(tableau, goal, rel, unif): new_tableau = tableau.copy() new_tableau.remove_goal(goal) out_port = PortVar(rel.block, rel.ident, rel.port) if isinstance(goal.variable, DSVar): assert (rel.block.outputs.has(rel.port.name)) new_tableau.add_stmt(VADPSource(out_port, \ genoplib.Var(goal.variable.var))) elif isinstance(goal.variable, PortVar): in_port = PortVar(goal.variable.block, \ goal.variable.ident, \ goal.variable.port) new_tableau.add_stmt(VADPConn(out_port, in_port)) elif isinstance(goal.variable, LawVar): in_port = LawVar(goal.variable.law, \ goal.variable.ident, \ goal.variable.var) new_tableau.add_stmt(VADPConn(out_port, in_port)) else: raise Exception("TODO: vadp should find/replace laws.") block_var = vadplib.PortVar(rel.block, rel.ident) vadp_cfg = VADPConfig(block_var, rel.modes) for stmt in tableau.vadp: if isinstance(stmt,VADPConfig) and \ stmt.same_target(vadp_cfg): stmt.merge(vadp_cfg) vadp_cfg = stmt data_vars = [] for vop, e in unif.assignments: if rel.block.data.has(vop.name): dat = rel.block.data[vop.name] data_vars += [vop.name] + dat.inputs if dat.type == blocklib.BlockDataType.EXPR: repl = {} for block_var, ds_var in map(lambda inp: unif.get_by_name(inp), \ dat.inputs): assert (ds_var.op == genoplib.OpType.VAR) repl[ds_var.name] = block_var assert (set(e.vars()) == set(repl.keys())) expr = e.substitute(repl) vadp_cfg.bind(vop.name, expr) else: vadp_cfg.bind(vop.name, e) # translate assignments to goals for vop,e in filter(lambda asgn: not asgn[0].name in data_vars, \ unif.assignments): v = vop.name # binding input port assignment if rel.block.inputs.has(v): sig_type = rel.block.inputs[v].type new_tableau.add_goal(Goal(PortVar(rel.block, \ rel.ident, \ rel.block.inputs[v]), \ sig_type,e)) elif v in rel.cstrs and \ rel.cstrs[v] == unifylib.UnifyConstraint.SAMEVAR: pass else: print(rel) print(rel.cstrs) print(rel.modes) raise Exception("unknown: %s=%s" % (v, e)) new_tableau.add_stmt(vadp_cfg) # if we used a freshly generated block, make sure to replace it replenish_block = (rel.ident == max(map(lambda r: r.ident \ if isinstance(r,PortRelation) \ and r.same_block(rel) else 0, \ tableau.relations))) # update existing relations in tableau to respect unification new_tableau.relations = [] for curr_rel in tableau.relations: # find port relations using the same block if isinstance(curr_rel,PortRelation) and \ curr_rel.same_block(rel) \ and curr_rel.ident == rel.ident: new_rel = curr_rel.copy() # do not add relation to new tableau if curr_rel.equals(rel): continue # could not concretize relation if not apply_vadp_config_to_relation(new_rel.block, \ vadp_cfg, \ unif, \ new_rel): continue new_tableau.add_relation(new_rel) else: new_tableau.add_relation(curr_rel.copy()) # add fresh block of same type if necessary if replenish_block: for output in rel.block.outputs: for expr, modes in output.relation.get_by_property(): new_rel = PortRelation(rel.block, rel.ident + 1, modes, output, expr) new_tableau.add_relation(new_rel) return new_tableau
def simplify_fuse_lut(dev,vadp,rule): target_stmt = None for stmt in vadp: print(">>>> %s" % stmt) if isinstance(stmt, tablib.VADPConfig) and \ isinstance(stmt.target, tablib.LawVar) and \ stmt.target.law == rule.law: target_stmt = stmt break print("FOUND: %s" % target_stmt) if target_stmt is None: return False,vadp new_vadp = [] identifier = target_stmt.target.ident mode = target_stmt.mode lut = vadplib.PortVar(dev.get_block('lut'),identifier) lut_cfg = vadplib.VADPConfig(lut,"*") lut_cfg.bind('e', target_stmt.assigns['e']) new_vadp.append(lut_cfg) adc = vadplib.PortVar(dev.get_block('adc'),identifier) adc_mode = adc.block.modes[["m"] if mode[1] == "m" else ["h"]] adc_cfg = vadplib.VADPConfig(adc,adc_mode) new_vadp.append(adc_cfg) dac = vadplib.PortVar(dev.get_block('dac'),identifier) dac_mode = dac.block.modes[["dyn","m"] if mode[1] == "m" else ["dyn","h"]] dac_cfg = vadplib.VADPConfig(dac,dac_mode) new_vadp.append(dac_cfg) new_vadp.append(vadplib.VADPConn(adc.make_port_var('z'), \ lut.make_port_var('x'))) new_vadp.append(vadplib.VADPConn(lut.make_port_var('z'), \ dac.make_port_var('x'))) for stmt in vadp: if isinstance(stmt, tablib.VADPConn) and \ isinstance(stmt.source, tablib.LawVar) and \ rule.same_usage(stmt.source): new_vadp.append(vadplib.VADPConn(dac.make_port_var('z'), \ stmt.sink)) elif isinstance(stmt, tablib.VADPConn) and \ isinstance(stmt.sink, tablib.LawVar) and \ rule.same_usage(stmt.sink): new_vadp.append(vadplib.VADPConn(stmt.source, \ adc.make_port_var('x'))) elif isinstance(stmt,tablib.VADPSource) and \ isinstance(stmt.port, tablib.LawVar) and \ rule.same_usage(stmt.port): new_vadp.append(vadplib.VAPSource(PortVar(dac,identifier,z), \ stmt.source)) else: print("unaffected: %s" % stmt) new_vadp.append(stmt) return True,new_vadp