diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml index d1e708f..a614366 100644 --- a/.github/workflows/generate.yml +++ b/.github/workflows/generate.yml @@ -13,33 +13,6 @@ on: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains a single job called "build" - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.x - uses: actions/setup-python@v5 - with: - # Semantic version range syntax or exact version of a Python version - python-version: '3.x' - # Optional - x64 or x86 architecture, defaults to x64 - architecture: 'x64' - # You can test your matrix by printing the current Python version - - name: Display Python version - run: python -c "import sys; print(sys.version)" - - name: Run generating adds and mults - run: python generate_test.py - - name: Run generating mac - run: python generate_mac.py - - name: Run generating axmults - run: python generate_axmuls.py - - name: Upload results - uses: actions/upload-artifact@v4 - with: - name: arithmetic-circuits-8 - path: test_circuits - test: runs-on: ubuntu-latest needs: build @@ -61,110 +34,25 @@ jobs: - name: Listing run: | ls - - name: Run 8b testing + - name: Run maji gate test run: | cd tests - bash test_circuits.sh + python3 test_maji.py cd .. - - name: Run 8b CGP testing + - name: Run Basic gates test run: | cd tests - bash test_circuits_cgp.sh + python3 test_maji_gates.py cd .. - - name: Run MAC testing + - name: Run 8b Adders test run: | cd tests - bash test_mac.sh + python3 test_maji_sadder.py + python3 test_maji_uadder.py cd .. - - name: Verilog testing + - name: Run 8b Muls test run: | cd tests - bash test_circuits_verilog.sh - cd .. - - - name: Python circuits testing - run: | - cd tests - python test_all.py - cd .. - - - name: Python ax testing - run: | - cd tests - python test_ax.py - cd .. - - - name: Python CGP testing - run: | - cd tests - python test_cgp.py - cd .. - - - name: Python Compare testing - run: | - cd tests - python test_compare.py - cd .. - - - name: Python Popcount testing - run: | - cd tests - python test_popcnt.py - cd .. - - - name: Python Reduce testing - run: | - cd tests - python test_reduce.py - cd .. - - test_python: - runs-on: ubuntu-latest - needs: build - strategy: - matrix: - python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11' ] - name: Python ${{ matrix.python-version }} test - steps: - - uses: actions/checkout@v4 - - name: Setup python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - architecture: x64 - - run: python -m pip install numpy pytest - - name: Run pytest - run: | - pytest - - # Only on main thread - documentation: - runs-on: ubuntu-latest - needs: test - if: github.ref == 'refs/heads/main' - steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.x - uses: actions/setup-python@v5 - with: - # Semantic version range syntax or exact version of a Python version - python-version: '3.x' - # Optional - x64 or x86 architecture, defaults to x64 - architecture: 'x64' - # You can test your matrix by printing the current Python version - - name: Display Python version - run: python -c "import sys; print(sys.version)" - - name: Install pdoc - run: python -m pip install pdoc3 - - name: Generate documentation - run: pdoc --html ariths_gen - - name: Upload results - uses: actions/upload-artifact@v4 - with: - name: documentation - path: html - - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@4.1.1 - with: - branch: gh-pages # The branch the action should deploy to. - folder: html/ariths_gen # The folder the action should deploy. + python3 test_maji_smul.py + python3 test_maji_umul.py + cd .. \ No newline at end of file diff --git a/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py index 4ec9dfd..6cff646 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py @@ -155,6 +155,6 @@ class SignedCarryIncrementAdder(UnsignedCarryIncrementAdder, GeneralCircuit): super().__init__(a=a, b=b, increment_block_size=increment_block_size, prefix=prefix, name=name, signed=True, **kwargs) # Additional XOR gates to ensure correct sign extension in case of sign addition - self.add_component(XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self)) - self.add_component(XorGateComponent(self.get_previous_component().out.get_wire(0), self.out.get_wire(-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self)) + self.add_component(XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self)) + self.add_component(XorGateComponent(self.get_previous_component().out.get_wire(0), self.out.get_wire(-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self)) self.out.connect(self.N, self.get_previous_component().out.get_wire(0)) diff --git a/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py index 0af25ed..d9b2019 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py @@ -164,6 +164,6 @@ class SignedCarrySelectAdder(UnsignedCarrySelectAdder, GeneralCircuit): super().__init__(a=a, b=b, select_block_size=select_block_size, prefix=prefix, name=name, signed=True, **kwargs) # Additional XOR gates to ensure correct sign extension in case of sign addition - self.add_component(XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self)) - self.add_component(XorGateComponent(self.get_previous_component().out.get_wire(0), self.out.get_wire(-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self)) + self.add_component(XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self)) + self.add_component(XorGateComponent(self.get_previous_component().out.get_wire(0), self.out.get_wire(-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self)) self.out.connect(self.N, self.get_previous_component().out.get_wire(0)) diff --git a/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py index e5df682..e35e6e4 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py @@ -159,8 +159,8 @@ class SignedCarrySkipAdder(UnsignedCarrySkipAdder, GeneralCircuit): super().__init__(a=a, b=b, bypass_block_size=bypass_block_size, prefix=prefix, name=name, signed=True, **kwargs) # Additional XOR gates to ensure correct sign extension in case of sign addition - sign_xor_1 = XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self) + sign_xor_1 = XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self) self.add_component(sign_xor_1) - sign_xor_2 = XorGateComponent(sign_xor_1.out.get_wire(0), self.get_previous_component(2).out.get_wire(), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self) + sign_xor_2 = XorGateComponent(sign_xor_1.out.get_wire(0), self.get_previous_component(2).out.get_wire(), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self) self.add_component(sign_xor_2) self.out.connect(self.N, sign_xor_2.out.get_wire(0)) diff --git a/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py b/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py index e92f193..e39fc55 100644 --- a/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py @@ -262,6 +262,6 @@ class SignedConditionalSumAdder(UnsignedConditionalSumAdder, GeneralCircuit): super().__init__(a=a, b=b, prefix=prefix, name=name, signed=True, **kwargs) # Additional XOR gates to ensure correct sign extension in case of sign addition - self.add_component(XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self)) - self.add_component(XorGateComponent(self.get_previous_component().out.get_wire(0), self.out.get_wire(-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate, count_disabled_gates=False)), parent_component=self)) + self.add_component(XorGateComponent(self.a.get_wire(self.N-1), self.b.get_wire(self.N-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self)) + self.add_component(XorGateComponent(self.get_previous_component().out.get_wire(0), self.out.get_wire(-1), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGateComponent, count_disabled_gates=False)), parent_component=self)) self.out.connect(self.N, self.get_previous_component().out.get_wire(0)) diff --git a/ariths_gen/one_bit_circuits/one_bit_components/three_input_one_bit_components.py b/ariths_gen/one_bit_circuits/one_bit_components/three_input_one_bit_components.py index 4030726..ad53b08 100644 --- a/ariths_gen/one_bit_circuits/one_bit_components/three_input_one_bit_components.py +++ b/ariths_gen/one_bit_circuits/one_bit_components/three_input_one_bit_components.py @@ -300,25 +300,25 @@ class TwoOneMultiplexer(ThreeInputOneBitCircuit): self.out = Bus(self.prefix+"_out", 1) # 2:1MUX logic - and_obj = AndGate(a=self.b, b=self.c, prefix=self.prefix+"_and"+str(self.get_instance_num(cls=AndGate)), parent_component=self) - self.add_component(and_obj) + and_obj1 = AndGate(a=self.b, b=self.c, prefix=self.prefix+"_and"+str(self.get_instance_num(cls=AndGate)), parent_component=self) + self.add_component(and_obj1) not_obj = NotGate(a=self.c, prefix=self.prefix+"_not"+str(self.get_instance_num(cls=NotGate)), parent_component=self) self.add_component(not_obj) - and_obj = AndGate(a=self.a, b=self.get_previous_component().out, prefix=self.prefix+"_and"+str(self.get_instance_num(cls=AndGate)), parent_component=self) - self.add_component(and_obj) + and_obj2 = AndGate(a=self.a, b=self.get_previous_component().out, prefix=self.prefix+"_and"+str(self.get_instance_num(cls=AndGate)), parent_component=self) + self.add_component(and_obj2) # final xor - obj_or2 = OrGate (a=self.get_previous_component(3).out, b=self.get_previous_component().out, prefix=self.prefix+"_or" +str(self.get_instance_num(cls=OrGate)), parent_component=self) - self.add_component(obj_or2) + obj_or = OrGate (a=and_obj1.out, b=and_obj2.out, prefix=self.prefix+"_or" +str(self.get_instance_num(cls=OrGate)), parent_component=self) + self.add_component(obj_or) - obj_and2 = AndGate(a=self.get_previous_component(3).out, b=self.get_previous_component().out, prefix=self.prefix+"_and"+str(self.get_instance_num(cls=AndGate)), parent_component=self) - self.add_component(obj_and2) + obj_and3 = AndGate(a=and_obj1.out, b=and_obj2.out, prefix=self.prefix+"_and"+str(self.get_instance_num(cls=AndGate)), parent_component=self) + self.add_component(obj_and3) # final sum - obj_maji = Maji(obj_or2.out, obj_and2.out, ConstantWireValue0(), [False, True, False], prefix=self.prefix+"_maji"+str(self.get_instance_num(cls=Maji)), parent_component=self) + obj_maji = Maji(obj_or.out, obj_and3.out, ConstantWireValue0(), [False, True, False], prefix=self.prefix+"_maji"+str(self.get_instance_num(cls=Maji)), parent_component=self) self.add_component(obj_maji) # Connection of MUX output wire diff --git a/tests/test_maji_adder.py b/tests/test_maji_adder.py deleted file mode 100644 index e8b2e63..0000000 --- a/tests/test_maji_adder.py +++ /dev/null @@ -1,40 +0,0 @@ - -from io import StringIO -import os, sys - -DIR_PATH = os.path.dirname(os.path.abspath(__file__)) -sys.path.insert(0, os.path.join(DIR_PATH, '..')) - -from ariths_gen.core.arithmetic_circuits import GeneralCircuit -from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder -from ariths_gen.wire_components import Bus - -from ariths_gen.pdk import * -import os - -class MultiMaji(GeneralCircuit): - def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "maji", **kwargs): - super().__init__(prefix=prefix, name=name, out_N=a.N, inputs=[a, b], **kwargs) - - self.out = Bus("out", a.N) - - assert a.N == b.N - - self.add = self.add_component(UnsignedRippleCarryAdder(a, b, prefix=self.prefix, name=f"u_rca{a.N}", inner_component=False)) - self.out.connect_bus(connecting_bus=self.add.out) - -# usage -if __name__ == "__main__": - maji = MultiMaji(Bus("a", 8), Bus("b", 8)) - - # try to test maji - for a in range(256): - for b in range(256): - testOut = maji(a, b) - expectedBus = (a + b) & 0xFF - - if (expectedBus != testOut): - print(f"expexted {a} + {b} = {expectedBus} have {testOut}") - exit(1) - - print("Test maji as Ripple Carry Adder OK") diff --git a/tests/test_maji_sadder.py b/tests/test_maji_sadder.py new file mode 100644 index 0000000..3fcef95 --- /dev/null +++ b/tests/test_maji_sadder.py @@ -0,0 +1,33 @@ + +from io import StringIO +import os, sys + +DIR_PATH = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.join(DIR_PATH, '..')) + +from ariths_gen.core.arithmetic_circuits import GeneralCircuit +from ariths_gen.multi_bit_circuits.adders import SignedRippleCarryAdder, SignedCarryLookaheadAdder, SignedBrentKungAdder, SignedCarryIncrementAdder, SignedCarrySkipAdder, SignedCarrySelectAdder, SignedConditionalSumAdder, SignedHanCarlsonAdder, SignedKnowlesAdder, SignedKoggeStoneAdder, SignedLadnerFischerAdder, SignedPGRippleCarryAdder, SignedSklanskyAdder +from ariths_gen.wire_components import Bus + +from ariths_gen.pdk import * +import os + +from ctypes import c_int8 + +# usage +if __name__ == "__main__": + + for adder in [SignedRippleCarryAdder, SignedCarryLookaheadAdder, SignedBrentKungAdder, SignedCarryIncrementAdder, SignedCarrySkipAdder, SignedCarrySelectAdder, SignedConditionalSumAdder, SignedHanCarlsonAdder, SignedKnowlesAdder, SignedKoggeStoneAdder, SignedLadnerFischerAdder, SignedPGRippleCarryAdder, SignedSklanskyAdder]: + maji = adder(Bus("a", 8), Bus("b", 8), prefix="", name=f"u_adder") + + # try to test maji + for a in range(256): + for b in range(256): + testOut = c_int8(maji(a, b)).value + expectedBus = c_int8(c_int8(a).value + c_int8(b).value).value + + if (expectedBus != testOut): + print(f"Test maji as {adder.__name__} FAIL expexted {a} + {b} = {expectedBus} have {testOut}") + exit(1) + + print(f"Test maji as {adder.__name__} OK") \ No newline at end of file diff --git a/tests/test_maji_smul.py b/tests/test_maji_smul.py new file mode 100644 index 0000000..34ff060 --- /dev/null +++ b/tests/test_maji_smul.py @@ -0,0 +1,32 @@ + +from io import StringIO +import os, sys + +DIR_PATH = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.join(DIR_PATH, '..')) + +from ariths_gen.core.arithmetic_circuits import GeneralCircuit +from ariths_gen.multi_bit_circuits.multipliers import SignedArrayMultiplier, SignedCarrySaveMultiplier, SignedDaddaMultiplier, SignedWallaceMultiplier +from ariths_gen.wire_components import Bus +from ctypes import c_int8, c_int16 + +from ariths_gen.pdk import * +import os + +# usage +if __name__ == "__main__": + + for multiplayer in [SignedArrayMultiplier, SignedCarrySaveMultiplier, SignedDaddaMultiplier, SignedWallaceMultiplier]: + maji = multiplayer(Bus("a", 8), Bus("b", 8), prefix="", name=f"u_mul") + + # try to test maji + for a in range(256): + for b in range(256): + testOut = c_int16(maji(a, b)).value + expectedBus = c_int16(c_int8(a).value * c_int8(b).value).value + + if (expectedBus != testOut): + print(f"Test maji as {multiplayer.__name__} FAIL expexted {a} * {b} = {expectedBus} have {testOut}") + exit(1) + + print(f"Test maji as {multiplayer.__name__} OK") diff --git a/tests/test_maji_uadder.py b/tests/test_maji_uadder.py new file mode 100644 index 0000000..1e2a29f --- /dev/null +++ b/tests/test_maji_uadder.py @@ -0,0 +1,33 @@ + +from io import StringIO +import os, sys + +DIR_PATH = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.join(DIR_PATH, '..')) + +from ariths_gen.core.arithmetic_circuits import GeneralCircuit +from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder, UnsignedCarryLookaheadAdder, UnsignedBrentKungAdder, UnsignedCarryIncrementAdder, UnsignedCarrySkipAdder, UnsignedCarrySelectAdder, UnsignedConditionalSumAdder, UnsignedHanCarlsonAdder, UnsignedKnowlesAdder, UnsignedKoggeStoneAdder, UnsignedLadnerFischerAdder, UnsignedPGRippleCarryAdder, UnsignedSklanskyAdder +from ariths_gen.wire_components import Bus + +from ariths_gen.pdk import * +import os + +from ctypes import c_uint8 + +# usage +if __name__ == "__main__": + + for adder in [UnsignedRippleCarryAdder, UnsignedCarryLookaheadAdder, UnsignedBrentKungAdder, UnsignedCarryIncrementAdder, UnsignedCarrySkipAdder, UnsignedCarrySelectAdder, UnsignedConditionalSumAdder, UnsignedHanCarlsonAdder, UnsignedKnowlesAdder, UnsignedKoggeStoneAdder, UnsignedLadnerFischerAdder, UnsignedPGRippleCarryAdder, UnsignedSklanskyAdder]: + maji = adder(Bus("a", 8), Bus("b", 8), prefix="", name=f"u_adder") + + # try to test maji + for a in range(256): + for b in range(256): + testOut = c_uint8(maji(a, b)).value + expectedBus = c_uint8(c_uint8(a).value + c_uint8(b).value).value + + if (expectedBus != testOut): + print(f"Test maji as {adder.__name__} FAIL expexted {a} + {b} = {expectedBus} have {testOut}") + exit(1) + + print(f"Test maji as {adder.__name__} OK") \ No newline at end of file diff --git a/tests/test_maji_umul.py b/tests/test_maji_umul.py new file mode 100644 index 0000000..dec0e2a --- /dev/null +++ b/tests/test_maji_umul.py @@ -0,0 +1,32 @@ + +from io import StringIO +import os, sys + +DIR_PATH = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, os.path.join(DIR_PATH, '..')) + +from ariths_gen.core.arithmetic_circuits import GeneralCircuit +from ariths_gen.multi_bit_circuits.multipliers import UnsignedArrayMultiplier, UnsignedCarrySaveMultiplier, UnsignedDaddaMultiplier, UnsignedWallaceMultiplier +from ariths_gen.wire_components import Bus +from ctypes import c_uint8, c_uint16 + +from ariths_gen.pdk import * +import os + +# usage +if __name__ == "__main__": + + for multiplayer in [UnsignedArrayMultiplier, UnsignedCarrySaveMultiplier, UnsignedDaddaMultiplier, UnsignedWallaceMultiplier]: + maji = multiplayer(Bus("a", 8), Bus("b", 8), prefix="", name=f"u_mul") + + # try to test maji + for a in range(256): + for b in range(256): + testOut = c_uint16(maji(a, b)) + expectedBus = c_uint16(c_uint8(a).value * c_uint8(b).value).value + + if (expectedBus != testOut): + print(f"Test maji as {multiplayer.__name__} FAIL expexted {a} * {b} = {expectedBus} have {testOut}") + exit(1) + + print(f"Test maji as {multiplayer.__name__} OK")