mirror of
https://github.com/ehw-fit/ariths-gen.git
synced 2025-04-22 06:41:22 +01:00
cnf implementation
This commit is contained in:
parent
a6060fa2a8
commit
b7764cd7c6
@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
from ariths_gen.core.logic_gate_circuits.logic_gate_circuit import (
|
from ariths_gen.core.logic_gate_circuits.logic_gate_circuit import (
|
||||||
OneInputLogicGate,
|
OneInputLogicGate,
|
||||||
TwoInputLogicGate
|
TwoInputLogicGate
|
||||||
@ -11,6 +12,8 @@ import inspect
|
|||||||
import copy
|
import copy
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
from ariths_gen.wire_components.wires import ConstantWireValue0, ConstantWireValue1
|
||||||
|
|
||||||
|
|
||||||
class GeneralCircuit():
|
class GeneralCircuit():
|
||||||
"""Class represents a general circuit and ensures its generation to various representations.
|
"""Class represents a general circuit and ensures its generation to various representations.
|
||||||
@ -856,3 +859,103 @@ class GeneralCircuit():
|
|||||||
file_object.write(self.get_parameters_cgp())
|
file_object.write(self.get_parameters_cgp())
|
||||||
file_object.write(self.get_triplets_cgp())
|
file_object.write(self.get_triplets_cgp())
|
||||||
file_object.write(self.get_outputs_cgp())
|
file_object.write(self.get_outputs_cgp())
|
||||||
|
|
||||||
|
|
||||||
|
# Generating flat C code representation of circuit
|
||||||
|
def get_cnf_code_flat(self, file_object):
|
||||||
|
"""Generates flat C code representation of corresponding arithmetic circuit.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||||
|
"""
|
||||||
|
assert self.out.N == 1, f"CNF generation only supports single output, not {self.out.N}"
|
||||||
|
|
||||||
|
self.cnf_vars = {}
|
||||||
|
self.cnf_varid = 1
|
||||||
|
self.cnf_has_const = False
|
||||||
|
self.cnf_var_comments = {}
|
||||||
|
|
||||||
|
for i in self.inputs:
|
||||||
|
for j in range(i.N):
|
||||||
|
self.get_cnfvar(i[j], create=True)
|
||||||
|
|
||||||
|
# hash array for gate outputs
|
||||||
|
hash_outputs = {}
|
||||||
|
for i, g in enumerate(self.circuit_gates):
|
||||||
|
assert g.out not in hash_outputs, f"Gate {g} has multiple outputs"
|
||||||
|
hash_outputs[g.out] = (i, g)
|
||||||
|
|
||||||
|
|
||||||
|
active_outputs = set()
|
||||||
|
|
||||||
|
# set ouput active
|
||||||
|
for i in range(self.out.N):
|
||||||
|
active_outputs.add(self.out[i].name)
|
||||||
|
|
||||||
|
print(active_outputs)
|
||||||
|
# for all gates back
|
||||||
|
for g in reversed(self.circuit_gates):
|
||||||
|
if g.out.name in active_outputs:
|
||||||
|
# set output active
|
||||||
|
active_outputs.add(g.a.name)
|
||||||
|
if hasattr(g, "b"):
|
||||||
|
active_outputs.add(g.b.name)
|
||||||
|
if hasattr(g, "c"):
|
||||||
|
active_outputs += (g.c.name)
|
||||||
|
print("Setting active output", g.out, " for gate ", g)
|
||||||
|
|
||||||
|
|
||||||
|
print("active outputs", active_outputs)
|
||||||
|
|
||||||
|
print(hash_outputs)
|
||||||
|
|
||||||
|
|
||||||
|
#file_object.write(self.get_includes_c())
|
||||||
|
#file_object.write(self.get_prototype_c())
|
||||||
|
allcnfs = []
|
||||||
|
for g in self.circuit_gates:
|
||||||
|
if g.out.name not in active_outputs:
|
||||||
|
continue
|
||||||
|
allcnfs += g.get_cnf_clause(self)
|
||||||
|
|
||||||
|
allcnfs.append([self.get_cnfvar(self.out[0])])
|
||||||
|
const1 = ConstantWireValue1()
|
||||||
|
if str(const1) in self.cnf_vars:
|
||||||
|
allcnfs.append([self.get_cnfvar(const1)])
|
||||||
|
|
||||||
|
|
||||||
|
# header p cnf <vars> <clauses>
|
||||||
|
file_object.write(f"p cnf {self.cnf_varid-1} {len(allcnfs)}\n")
|
||||||
|
|
||||||
|
file_object.write("c varmap={}\n".format(json.dumps(self.cnf_var_comments)))
|
||||||
|
for c in allcnfs:
|
||||||
|
file_object.write(" ".join(map(str, c)) + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_cnfvar(self, wire : Wire, create = False):
|
||||||
|
wireid = str(wire)
|
||||||
|
if wireid in self.cnf_vars:
|
||||||
|
assert not create, f"Wire {wireid} already found in CNF vars for {wire}"
|
||||||
|
elif wire.is_const():
|
||||||
|
# create FALSE variable
|
||||||
|
print("Creating new CNF var for constant wires", wire, " id ", wireid)
|
||||||
|
self.cnf_vars[str(ConstantWireValue0())] = -self.cnf_varid
|
||||||
|
self.cnf_vars[str(ConstantWireValue1())] = self.cnf_varid
|
||||||
|
self.cnf_var_comments[self.cnf_varid] = True
|
||||||
|
|
||||||
|
|
||||||
|
self.cnf_varid += 1
|
||||||
|
else:
|
||||||
|
assert create, f"Wire {wireid} not found in CNF vars"
|
||||||
|
print("Creating new CNF var for wire", wire, " id ", wireid)
|
||||||
|
self.cnf_var_comments[self.cnf_varid] = wire.name
|
||||||
|
self.cnf_vars[wireid] = self.cnf_varid
|
||||||
|
self.cnf_varid += 1
|
||||||
|
return self.cnf_vars[wireid]
|
||||||
|
|
||||||
|
def set_cnfvar(self, wire : Wire, value : int):
|
||||||
|
""" for buffers and inverters """
|
||||||
|
wireid = str(wire)
|
||||||
|
assert not wireid in self.cnf_vars, f"Wire {wireid} already found in CNF vars for {wire}"
|
||||||
|
self.cnf_vars[wireid] = value
|
@ -500,6 +500,9 @@ class TwoInputLogicGate():
|
|||||||
file_object.write(self.get_parameters_cgp())
|
file_object.write(self.get_parameters_cgp())
|
||||||
file_object.write(self.get_gate_triplet_cgp())
|
file_object.write(self.get_gate_triplet_cgp())
|
||||||
|
|
||||||
|
def get_cnf_clause(self, parent):
|
||||||
|
raise NotImplementedError(f"CNF generation is not implemented for this class. {self.__class__.__name__}")
|
||||||
|
|
||||||
|
|
||||||
class TwoInputInvertedLogicGate(TwoInputLogicGate):
|
class TwoInputInvertedLogicGate(TwoInputLogicGate):
|
||||||
"""Class representing two input inverted logic gates.
|
"""Class representing two input inverted logic gates.
|
||||||
|
@ -61,6 +61,41 @@ class AndGate(TwoInputLogicGate):
|
|||||||
return f".names {self.a.get_wire_value_blif()} {self.b.get_wire_value_blif()} {self.out.get_wire_value_blif()}\n" + \
|
return f".names {self.a.get_wire_value_blif()} {self.b.get_wire_value_blif()} {self.out.get_wire_value_blif()}\n" + \
|
||||||
f"11 1\n"
|
f"11 1\n"
|
||||||
|
|
||||||
|
def get_cnf_clause(self, parent):
|
||||||
|
"""Generates CNF clause representing AND gate Boolean function using its truth table."""
|
||||||
|
|
||||||
|
|
||||||
|
x = parent.get_cnfvar(self.a)
|
||||||
|
y = parent.get_cnfvar(self.b)
|
||||||
|
|
||||||
|
if x == -y: # a AND ~a
|
||||||
|
z = parent.get_cnfvar(ConstantWireValue0())
|
||||||
|
parent.set_cnfvar(self.out, z)
|
||||||
|
return []
|
||||||
|
|
||||||
|
z = parent.get_cnfvar(self.out, create = True)
|
||||||
|
|
||||||
|
# return f"[[{x},-{z}],[{y},-{z}],[{z},-{x},-{y}]]"
|
||||||
|
return [[x,-z],[y,-z],[-x,-y,z]]
|
||||||
|
# """
|
||||||
|
# auto z = getnewvar();
|
||||||
|
# z je vystupni promenna hradla
|
||||||
|
|
||||||
|
# x <- getvar(in1)
|
||||||
|
# y <- getvar(in2)
|
||||||
|
|
||||||
|
# do CNF ukladam:
|
||||||
|
|
||||||
|
# XOR:
|
||||||
|
|
||||||
|
# [[-x,y,z],[x,-y,z],[-x,-y,-z],[x,y,-z]]
|
||||||
|
|
||||||
|
# AND:
|
||||||
|
|
||||||
|
# [[x,-z],[y,-z],[-x,-y-,-z]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NandGate(TwoInputInvertedLogicGate):
|
class NandGate(TwoInputInvertedLogicGate):
|
||||||
"""Class representing two input NAND gate.
|
"""Class representing two input NAND gate.
|
||||||
@ -281,7 +316,7 @@ class XorGate(TwoInputLogicGate):
|
|||||||
# If constant input is present, logic gate is not generated and corresponding
|
# If constant input is present, logic gate is not generated and corresponding
|
||||||
# input value is propagated to the output to connect to other components
|
# input value is propagated to the output to connect to other components
|
||||||
if a.is_const() and a.value == 1:
|
if a.is_const() and a.value == 1:
|
||||||
assert self.parent_component, "Parent component for gate {self} is not defined"
|
assert self.parent_component, f"Parent component for gate {self} is not defined"
|
||||||
output = NotGate(a=b, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
output = NotGate(a=b, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
@ -290,7 +325,7 @@ class XorGate(TwoInputLogicGate):
|
|||||||
self.out = b
|
self.out = b
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
elif b.is_const() and b.value == 1:
|
elif b.is_const() and b.value == 1:
|
||||||
assert self.parent_component, "Parent component for gate {self} is not defined"
|
assert self.parent_component, f"Parent component for gate {self} is not defined"
|
||||||
output = NotGate(a=a, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
output = NotGate(a=a, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
@ -301,6 +336,31 @@ class XorGate(TwoInputLogicGate):
|
|||||||
else:
|
else:
|
||||||
self.out = Wire(name=prefix)
|
self.out = Wire(name=prefix)
|
||||||
|
|
||||||
|
|
||||||
|
def get_cnf_clause(self, parent):
|
||||||
|
z = parent.get_cnfvar(self.out, create = True)
|
||||||
|
x = parent.get_cnfvar(self.a)
|
||||||
|
y = parent.get_cnfvar(self.b)
|
||||||
|
|
||||||
|
return [[ -x, y, z], [x,-y,z],[x,y,-z],[x,-y,-z]]
|
||||||
|
|
||||||
|
# """
|
||||||
|
# auto z = getnewvar();
|
||||||
|
# z je vystupni promenna hradla
|
||||||
|
|
||||||
|
# x <- getvar(in1)
|
||||||
|
# y <- getvar(in2)
|
||||||
|
|
||||||
|
# do CNF ukladam:
|
||||||
|
|
||||||
|
# XOR:
|
||||||
|
|
||||||
|
# [[-x,y,z],[x,-y,z],[-x,-y,-z],[x,y,-z]]
|
||||||
|
|
||||||
|
# AND:
|
||||||
|
|
||||||
|
# [[x,-z],[y,-z],[-x,-y-,-z]]
|
||||||
|
|
||||||
""" BLIF CODE GENERATION """
|
""" BLIF CODE GENERATION """
|
||||||
def get_function_blif(self):
|
def get_function_blif(self):
|
||||||
"""Generates Blif code representing XOR gate Boolean function using its truth table.
|
"""Generates Blif code representing XOR gate Boolean function using its truth table.
|
||||||
@ -432,3 +492,8 @@ class NotGate(OneInputLogicGate):
|
|||||||
else:
|
else:
|
||||||
return f".names {self.a.get_wire_value_blif()} {self.out.get_wire_value_blif()}\n" + \
|
return f".names {self.a.get_wire_value_blif()} {self.out.get_wire_value_blif()}\n" + \
|
||||||
f"0 1\n"
|
f"0 1\n"
|
||||||
|
|
||||||
|
def get_cnf_clause(self, parent):
|
||||||
|
x = parent.get_cnfvar(self.a)
|
||||||
|
parent.set_cnfvar(self.out, -x)
|
||||||
|
return []
|
Loading…
x
Reference in New Issue
Block a user