Beispiel #1
0
def test():
    #for arg in argv[1:]:
    #    inputs, outputs, node_map = readbench.readBench(arg)
    a = ckt.InputNode('a')
    b = ckt.InputNode('b')
    c = ckt.InputNode('c')
    f = a & b & c
    g = (a & b) | (~a & ~b)
    unates = getUnateNodes([f, g])
    for u in unates:
        print(u)
Beispiel #2
0
def getUnateNodes(outputs):
    S = Solver()

    supports = set()
    gates = set()
    for o in outputs:
        supports = supports.union(o.support())
        gates = gates.union(o.transitiveFaninCone())
    # topo sort.
    ckt.computeLevels(gates)

    def newVar(n):
        return S.newVar()

    cnf = []
    nmap1 = {}
    nmap2 = {}
    cnf += adapter.gateSetToCNF(gates, nmap1, newVar)
    cnf += adapter.gateSetToCNF(gates, nmap2, newVar)

    iMap = {}
    for inp in supports:
        i1 = ckt.InputNode(inp.name + "__1")
        i2 = ckt.InputNode(inp.name + "__2")
        iEq = ckt.XnorGate(i1, i2)
        nmap = {i1: nmap1[inp], i2: nmap2[inp]}
        cnf += adapter.circuitToCNF(iEq, nmap, newVar)
        iMap[inp] = (nmap[i1], nmap[i2], nmap[iEq])

    for c in cnf:
        S.addClause(*c)

    unates = set()
    for gate in gates:
        if gate.is_input():
            continue
        f0 = nmap1[gate]
        f1 = nmap2[gate]
        unate = True
        for i in supports:
            c1 = checkUnate(S, i, f0, f1, iMap, 0)
            c2 = checkUnate(S, i, f0, f1, iMap, 1)
            if not c1 and not c2:
                unate = False
                break
        if unate:
            unates.add(gate)

    return unates
def isonecounter_v1(eq, ps, k):
    subs = {pi: ckt.InputNode(pi.name + '_') for pi in ps}
    eqp = eq.subst(subs)
    ds = [(pi ^ subs[pi]) for pi in ps]
    eqHD = hd(ds, 2 * k)
    y = ckt.AndGate(eq, eqp, eqHD)

    inps = [(pi, subs[pi]) for pi in ps]

    S = Solver()
    nmap = {}
    clauses = adapter.circuitToCNF(y, nmap, lambda n: S.newVar())
    for pi, qi in inps:
        S.freeze(nmap[pi])
        S.freeze(nmap[qi])
    for c in clauses:
        S.addClause(*c)
    l = nmap[y]
    S.addClause(l)

    r = S.solve()
    if not r:
        return False, None

    # gather all the input values.
    ms, ns = [], []
    for pi, qi in inps:
        ai, bi = nmap[pi], nmap[qi]
        mi = int(S.modelValue(ai))
        ni = int(S.modelValue(bi))
        ms.append(mi)
        ns.append(ni)

    # assert the obvious ones.
    key = {}
    for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns):
        ai, bi = nmap[pi], nmap[qi]
        if mi == ni:
            key[pi] = mi
            #S.addClause(valToLit(key[pi], ai))
            #S.addClause(valToLit(key[pi], bi))

    # now handle the rest.
    assumps = []
    for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns):
        ai, bi = nmap[pi], nmap[qi]
        if mi != ni:
            r1 = S.solve(valToLit(mi, ai), valToLit(mi, bi))
            r2 = S.solve(valToLit(ni, ai), valToLit(ni, bi))
            if r1 == True and r2 == False:
                key[pi] = mi
            elif r1 == False and r2 == True:
                key[pi] = ni
            else:
                return False, None

            #S.addClause(valToLit(key[pi], ai))
            #S.addClause(valToLit(key[pi], bi))
    ks = [key[pi] for pi in ps]
    return True, ks
def readFileObject(fobj):
    "Reads a bench file and returns the tuple (inps, outs, node_map)."
    fanins = {}
    node_map = {}
    output_names = []
    inputs = []
    for l in fobj.readlines():
        f = []
        l = l.strip()
        if len(l) == 0 or l.startswith('#'):
            continue
        if 'INPUT(' in l:
            name = l.replace("INPUT(", "").replace(")", "")
            node = ckt.InputNode(name)
            node_map[name] = node
            inputs.append(node)
        elif 'OUTPUT(' in l:
            name = l.replace("OUTPUT(", "").replace(")", "")
            output_names.append(name)
        elif '=' in l:
            parts = [p.strip() for p in l.split('=')]
            assert len(parts) == 2
            gate_name = parts[0]
            rhs = parts[1]
            if rhs == 'VDD':
                node_map[gate_name] = ckt.Const1Node()
            else:
                gate_type = rhs[:rhs.find('(')]
                within_bracket = rhs[rhs.find('(')+1:rhs.find(')')]
                fanin_names = [p.strip() for p in within_bracket.split(',')]
                fanins = [node_map[fn] for fn in fanin_names]
                if gate_type == 'AND':
                    g = ckt.AndGate(*fanins)
                elif gate_type == 'OR':
                    g = ckt.OrGate(*fanins)
                elif gate_type == 'NOT':
                    g = ckt.NotGate(*fanins)
                elif gate_type == 'XOR':
                    g = ckt.XorGate(*fanins)
                elif gate_type == 'XNOR':
                    g = ckt.XnorGate(*fanins)
                elif gate_type == 'NAND':
                    g = ckt.NandGate(*fanins)
                elif gate_type == 'NOR':
                    g = ckt.NorGate(*fanins)
                elif gate_type == 'BUF' or gate_type == 'BUFF':
                    g = ckt.BufGate(*fanins)
                else:
                    assert False, gate_type
                node_map[gate_name] = g
                g.name = gate_name
        else:
            assert False, l
    outputs = []
    for out_name in output_names:
        output = node_map[out_name]
        output.name = out_name
        outputs.append(output)

    return inputs, outputs, node_map
def test(k, h):
    sys.setrecursionlimit(8192)

    ps = [ckt.InputNode('p%d' % i) for i in range(k)]
    fs = [random.randint(1, 1) for i in range(len(ps))]
    ys = [~pi if fi else pi for (fi, pi) in itertools.izip(fs, ps)]
    eq = hd(ys, h)

    r, ks = isonecounter(eq, ps, h, None)
    if r:
        print('fs:', fs)
        print('ks:', ks)
        assert fs == ks
    else:
        print('TROUBLE!')
def test():
    xs = [ckt.InputNode('x%d' % i) for i in range(32)]
    ys = onecount(xs)
    eq4 = ckt.AndGate(~ys[0], ~ys[1], ys[2], ~ys[3])

    print(len(eq4))
    return

    S = Solver()
    nmap = {}
    clauses = circuitToCNF(eq4, nmap, lambda n: S.newVar())
    for c in clauses:
        S.addClause(*c)

    tt = []
    while S.solve():
        blockingClause = []
        row = []
        for xi in itertools.chain(reversed(xs)):
            li = nmap[xi]
            vi = S.modelValue(li)
            row.append(vi)
            if vi: blockingClause.append(-li)
            else: blockingClause.append(li)
        num_ones = sum(row)
        li = nmap[eq4]
        vi = S.modelValue(li)
        row.append(vi)
        tt.append(row)
        S.addClause(*blockingClause)
        assert (num_ones == 4) == vi
    tt.sort()
    for row in tt:

        def listToString(l):
            return ''.join(str(int(i)) for i in l)

        p1 = listToString(row[:len(xs)])
        p2 = listToString(row[len(xs):])
        print('%s | %s ' % (p1, p2))
def isonecounter_v4(eq, ps, k, log):
    subs = {pi: ckt.InputNode(pi.name + '_') for pi in ps}
    id_map = {pi: pi for pi in ps}
    S = Solver()
    nmap = {}
    for idx, xi in enumerate(ps):
        for xj in ps[idx + 1:]:
            new_map = id_map.copy()
            new_map[xi] = subs[xi]
            eq1 = eq.subst(new_map)
            new_map.pop(xi)

            new_map1 = new_map.copy()
            new_map1[subst[xi]] = subst[xi]
            new_map1[xj] = xi
            eq2 = eq1.subst(new_map1)
            new_map2.pop(xj)

            new_map2 = new_map1.copy()
            new_map2[xi] = xi
            new_map2[subst[xi]] = xj
            eq3 = eq2.subst(new_map2)

            or1 = eq3 ^ eq
def isonecounter_v3(eq, ps, k, log):
    subs = {pi: ckt.InputNode(pi.name + '_') for pi in ps}
    eqp = eq.subst(subs)
    ds = [(pi ^ subs[pi]) for pi in ps]
    eqHD = hd(ds, 2 * k)
    y = ckt.AndGate(eq, eqp, eqHD)

    inps = [(pi, subs[pi]) for pi in ps]
    S = Solver()
    nmap = {}
    clauses = adapter.circuitToCNF(y, nmap, lambda n: S.newVar())
    # freeze literals
    for pi, qi in inps:
        S.freeze(nmap[pi])
        S.freeze(nmap[qi])
    for di in ds:
        S.freeze(nmap[di])
    # add clauses.
    for c in clauses:
        S.addClause(*c)
    l = nmap[y]
    S.addClause(l)

    r = S.solve()
    if not r:
        return False, None

    # gather the first round of keys.
    assumps = []
    key = {}
    for ((pi, qi), di) in itertools.izip(inps, ds):
        ai, bi = nmap[pi], nmap[qi]
        mi = int(S.modelValue(ai))
        ni = int(S.modelValue(bi))
        if mi == ni:
            key[pi] = mi
        else:
            li = nmap[di]
            assumps.append(-li)

    r = S.solve(*assumps)
    if not r:
        return False, None

    # and now the second round of keys.
    for ((pi, qi), di) in itertools.izip(inps, ds):
        ai, bi = nmap[pi], nmap[qi]
        mi = int(S.modelValue(ai))
        ni = int(S.modelValue(bi))
        if mi == ni:
            key[pi] = mi

    ks = [key[pi] for pi in ps]
    if log:
        pkl.dump(eq, log)
        pkl.dump(ps, log)
        pkl.dump(ks, log)
        log.flush()
        #log.close()

    if checkKey(eq, ps, ks, k):
        return True, ks
    else:
        return False, None
def isonecounter_v2(eq, ps, k):
    S = Solver()

    subs = {pi: ckt.InputNode(pi.name + '_') for pi in ps}
    eqp = eq.subst(subs)
    y = ckt.AndGate(eq, eqp)
    inps = [(pi, subs[pi]) for pi in ps]
    ds = [(pi ^ subs[pi]) for pi in ps]

    nmap = {}
    ckt_clauses = adapter.circuitToCNF(y, nmap, lambda n: S.newVar())
    for di in ds:
        ckt_clauses += adapter.circuitToCNF(di, nmap, lambda n: S.newVar())

    zeros = []
    dlits = [nmap[di] for di in ds]
    while not isPowOf2(len(dlits)):
        zi = S.newVar()
        dlits.append(zi)
        zeros.append(zi)
    (snw_clauses, es) = sortNetwork(TWO_COMP_EQ, dlits, lambda: S.newVar())
    for pi, qi in inps:
        S.freeze(nmap[pi])
        S.freeze(nmap[qi])
    for c in zeros:
        S.addClause(-c)
    for c in itertools.chain(ckt_clauses, snw_clauses):
        S.addClause(*c)
    l = nmap[y]
    S.addClause(l)
    for i, ei in enumerate(es):
        if i < 2 * k:
            S.addClause(ei)
        else:
            S.addClause(-ei)

    r = S.solve()
    if not r:
        return False, None

    # gather all the input values.
    ms, ns = [], []
    for pi, qi in inps:
        ai, bi = nmap[pi], nmap[qi]
        mi = int(S.modelValue(ai))
        ni = int(S.modelValue(bi))
        ms.append(mi)
        ns.append(ni)

    # assert the obvious ones.
    key = {}
    for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns):
        ai, bi = nmap[pi], nmap[qi]
        if mi == ni:
            key[pi] = mi
            #S.addClause(valToLit(key[pi], ai))
            #S.addClause(valToLit(key[pi], bi))

    # now handle the rest.
    assumps = []
    for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns):
        ai, bi = nmap[pi], nmap[qi]
        if mi != ni:
            r1 = S.solve(valToLit(mi, ai), valToLit(mi, bi))
            r2 = S.solve(valToLit(ni, ai), valToLit(ni, bi))
            if r1 == True and r2 == False:
                key[pi] = mi
            elif r1 == False and r2 == True:
                key[pi] = ni
            else:
                return False, None

            #S.addClause(valToLit(key[pi], ai))
            #S.addClause(valToLit(key[pi], bi))
    ks = [key[pi] for pi in ps]
    return True, ks