From 2e0d3de856bc194565be8552b565ea966b4ea785 Mon Sep 17 00:00:00 2001 From: zvasicek <37452722+zvasicek@users.noreply.github.com> Date: Mon, 20 Jan 2025 13:03:20 +0100 Subject: [PATCH] dual logic --- .../arithmetic_circuits/general_circuit.py | 45 ++++++++++++------- .../logic_gate_circuits/logic_gate_circuit.py | 8 ++++ .../logic_gates/logic_gates.py | 7 +++ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/ariths_gen/core/arithmetic_circuits/general_circuit.py b/ariths_gen/core/arithmetic_circuits/general_circuit.py index 301453f..4662b2f 100644 --- a/ariths_gen/core/arithmetic_circuits/general_circuit.py +++ b/ariths_gen/core/arithmetic_circuits/general_circuit.py @@ -890,7 +890,7 @@ class GeneralCircuit(): 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("Setting active output", g.out, " for gate ", g) inputs = [] @@ -907,7 +907,7 @@ class GeneralCircuit(): return inputs, gates # Generating flat C code representation of circuit - def get_cnf_code_flat(self, file_object): + def get_cnf_code_flat(self, file_object, use_dual_logic=False): """Generates flat C code representation of corresponding arithmetic circuit. Args: @@ -931,22 +931,37 @@ class GeneralCircuit(): #file_object.write(self.get_includes_c()) #file_object.write(self.get_prototype_c()) allcnfs = [] - for g in active_gates: - allcnfs += g.get_cnf_clause(self) + if (use_dual_logic): + for g in active_gates: + allcnfs += g.get_cnf_clause_dual(self) - allcnfs.append([self.get_cnfvar(self.out[0])]) - const1 = ConstantWireValue1() - if str(const1) in self.cnf_vars: - allcnfs.append([self.get_cnfvar(const1)]) + outvar = self.get_cnfvar(self.out[0]) + allcnfs.append([-outvar]) + const1 = ConstantWireValue1() + if str(const1) in self.cnf_vars: + allcnfs.append([-self.get_cnfvar(const1)]) - # header p cnf - file_object.write(f"p cnf {self.cnf_varid-1} {len(allcnfs)}\n") + else: + for g in active_gates: + allcnfs += g.get_cnf_clause(self) - file_object.write("c varmap={}\n".format(json.dumps(self.cnf_var_comments))) - for c in allcnfs: - file_object.write(" ".join(map(str, c + [0])) + "\n") + outvar = self.get_cnfvar(self.out[0]) + allcnfs.append([outvar]) + const1 = ConstantWireValue1() + if str(const1) in self.cnf_vars: + allcnfs.append([self.get_cnfvar(const1)]) + + if hasattr(file_object, 'write'): + # header p cnf + 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 + [0])) + "\n") + + return allcnfs, outvar def get_cnfvar(self, wire : Wire, create = False): @@ -955,7 +970,7 @@ class GeneralCircuit(): 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) + #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 @@ -964,7 +979,7 @@ class GeneralCircuit(): 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) + #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 diff --git a/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py b/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py index f635d91..90e3601 100644 --- a/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py +++ b/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py @@ -86,6 +86,8 @@ class TwoInputLogicGate(): # Obtaining the caller object to gain access into its `components` list Used for adding NOT gates as a replacement for two input logic gates with constant input (optimalization) # Also used to obtain caller object's `prefix` name for proper wire names generation of flat/hier representations self.parent_component = parent_component + # Reference to the dual gate (duality logic) + self.dual_gate = None """ C CODE GENERATION """ # FLAT C # @@ -500,6 +502,12 @@ class TwoInputLogicGate(): file_object.write(self.get_parameters_cgp()) file_object.write(self.get_gate_triplet_cgp()) + def get_cnf_clause_dual(self, parent): + if self.dual_gate is None: + raise NotImplementedError(f"CNF generation is not implemented for this class. {self.__class__.__name__}") + return self.dual_gate.get_cnf_clause(self, parent) + + def get_cnf_clause(self, parent): raise NotImplementedError(f"CNF generation is not implemented for this class. {self.__class__.__name__}") diff --git a/ariths_gen/one_bit_circuits/logic_gates/logic_gates.py b/ariths_gen/one_bit_circuits/logic_gates/logic_gates.py index cb10174..5c95bd4 100644 --- a/ariths_gen/one_bit_circuits/logic_gates/logic_gates.py +++ b/ariths_gen/one_bit_circuits/logic_gates/logic_gates.py @@ -28,6 +28,7 @@ class AndGate(TwoInputLogicGate): self.gate_type = "and_gate" self.cgp_function = 2 self.operator = "&" + self.dual_gate = OrGate # Logic gate output wire generation based on input values # If constant input is present, logic gate is not generated and corresponding @@ -107,6 +108,7 @@ class NandGate(TwoInputInvertedLogicGate): self.gate_type = "nand_gate" self.cgp_function = 5 self.operator = "&" + self.dual_gate = NOrGate # Logic gate output wire generation based on input values # If constant input is present, logic gate is not generated and corresponding @@ -191,6 +193,7 @@ class OrGate(TwoInputLogicGate): self.gate_type = "or_gate" self.cgp_function = 3 self.operator = "|" + self.dual_gate = AndGate # Logic gate output wire generation based on input values # If constant input is present, logic gate is not generated and corresponding @@ -269,6 +272,7 @@ class NorGate(TwoInputInvertedLogicGate): self.gate_type = "nor_gate" self.cgp_function = 6 self.operator = "|" + self.dual_gate = NandGate # Logic gate output wire generation based on input values # If constant input is present, logic gate is not generated and corresponding @@ -353,6 +357,7 @@ class XorGate(TwoInputLogicGate): self.gate_type = "xor_gate" self.cgp_function = 4 self.operator = "^" + self.dual_gate = XnorGate # Logic gate output wire generation based on input values # If constant input is present, logic gate is not generated and corresponding @@ -436,6 +441,7 @@ class XnorGate(TwoInputInvertedLogicGate): self.gate_type = "xnor_gate" self.cgp_function = 7 self.operator = "^" + self.dual_gate = XorGate # Logic gate output wire generation based on input values # If constant input is present, logic gate is not generated and corresponding @@ -518,6 +524,7 @@ class NotGate(OneInputLogicGate): self.gate_type = "not_gate" self.cgp_function = 1 self.operator = "~" + self.dual_gate = NotGate # Logic gate output wire generation based on input values # If constant input is present, logic gate is not generated and corresponding