diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml index 1da9788..ae1a56e 100644 --- a/.github/workflows/generate.yml +++ b/.github/workflows/generate.yml @@ -30,6 +30,8 @@ jobs: run: python -c "import sys; print(sys.version)" - name: Run generating run: python generate_test.py + - name: Run generating + run: python generate_mac.py - name: Upload results uses: actions/upload-artifact@v1.0.0 with: @@ -62,6 +64,11 @@ jobs: cd tests bash test_circuits_cgp.sh cd .. + - name: Run MAC testing + run: | + cd tests + bash test_mac.sh + cd .. # Only on main thread documentation: diff --git a/generate_mac.py b/generate_mac.py new file mode 100644 index 0000000..173bad0 --- /dev/null +++ b/generate_mac.py @@ -0,0 +1,60 @@ + +from ariths_gen.core.arithmetic_circuits import GeneralCircuit +from ariths_gen.wire_components import Bus, Wire +from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder +from ariths_gen.multi_bit_circuits.multipliers import UnsignedArrayMultiplier +import os + +class MAC(GeneralCircuit): + def __init__(self, A:Bus, B:Bus, R:Bus): + self.prefix = "mac" + super().__init__([A, B, R]) + assert A.N == B.N + assert R.N == 2 * A.N + + + if False: + # Je zapotřebí zajistit ještě unikátnost jmen podkomponent a jejich vodičů pro správné generování + mul_a = Bus(prefix=f"{self.prefix}_mul_a", wires_list=A.bus) + mul_b = Bus(prefix=f"{self.prefix}_mul_b", wires_list=B.bus) + self.mul = self.add_component(UnsignedArrayMultiplier(a=mul_a, b=mul_b, prefix=f"{self.prefix}_mul")) + + add_a = Bus(prefix=f"{self.prefix}_add_a", N=self.mul.out.N) + add_b = Bus(prefix=f"{self.prefix}_add_b", wires_list=R.bus) + # Kvůli správnému generování je potřeba správně napojit vodiče mezi mul a add + [add_a.connect(o, self.mul.out.get_wire(o), inserted_wire_desired_index=o) for o in range(0, self.mul.out.N)] + + self.add = self.add_component(UnsignedRippleCarryAdder(a=add_a, b=add_b, prefix=f"{self.prefix}_add")) + + # Bylo potřeba upravit definici pro výstupní sběrnici (vázanou na název top level obvodu ("ma") a mající délku jako výstup z adderu) + self.out = Bus(self.prefix+"_out", self.add.out.N) + + # Nakonec je potřeba napojit výstup adderu na výstup mac + [self.out.connect(o, self.add.out.get_wire(o), inserted_wire_desired_index=o) for o in range(0, self.out.N)] + + else: + # Je zapotřebí zajistit ještě unikátnost jmen podkomponent a jejich vodičů pro správné generování + mul_prefix = self.prefix + "_" + UnsignedArrayMultiplier(a=A, b=B).prefix + str(A.N) + mul_a = Bus(prefix=f"{mul_prefix}_a", wires_list=A.bus) + mul_b = Bus(prefix=f"{mul_prefix}_b", wires_list=B.bus) + self.mul = self.add_component(UnsignedArrayMultiplier(a=mul_a, b=mul_b, prefix=mul_prefix)) + + add_prefix = self.prefix + "_" + UnsignedRippleCarryAdder(a=R, b=self.mul.out).prefix + str(R.N) + add_a = Bus(prefix=f"{add_prefix}_a", N=self.mul.out.N) + add_b = Bus(prefix=f"{add_prefix}_b", wires_list=R.bus) + # Kvůli správnému generování je potřeba správně napojit vodiče mezi mul a add + [add_a.connect(o, self.mul.out.get_wire(o), inserted_wire_desired_index=o) for o in range(0, self.mul.out.N)] + + self.add = self.add_component(UnsignedRippleCarryAdder(a=add_a, b=add_b, prefix=add_prefix)) + + # Bylo potřeba upravit definici pro výstupní sběrnici (vázanou na název top level obvodu ("ma") a mající délku jako výstup z adderu) + self.out = Bus(self.prefix+"_out", self.add.out.N) + + # Nakonec je potřeba napojit výstup adderu na výstup mac + [self.out.connect(o, self.add.out.get_wire(o), inserted_wire_desired_index=o) for o in range(0, self.out.N)] +# usage +os.makedirs("test_circuits/mac", exist_ok=True) +mymac = MAC(Bus("a",8), Bus("b", 8), Bus("acc", 16)) +mymac.get_v_code_hier(open("test_circuits/mac/mac_hier.v", "w")) +mymac.get_c_code_hier(open("test_circuits/mac/mac_hier.c", "w")) +mymac.get_c_code_flat(open("test_circuits/mac/mac_flat.c", "w")) diff --git a/tests/mac.c b/tests/mac.c new file mode 100644 index 0000000..653a6a9 --- /dev/null +++ b/tests/mac.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +uint64_t mac(uint64_t a,uint64_t b,uint64_t acc); + + +int main() { + int result = 0; + + srand(42); + for(int i = 0; i < 10000; i++) { + uint64_t a, b, acc; + a = rand() % 256; + b = rand() % 256; + acc = rand() % 65536; + result = (a * b) + acc; + + assert(result == mac(a, b, acc)); + } + return 0; +} \ No newline at end of file diff --git a/tests/test_mac.sh b/tests/test_mac.sh new file mode 100644 index 0000000..04d9d9d --- /dev/null +++ b/tests/test_mac.sh @@ -0,0 +1,35 @@ +#!/usr/bin/bash + +valid=1 + +test_circuit_mac () { + local type=$1 + + + + for mode in "flat" "hier"; do + echo -e "===== Testing \e[33m$circuit\e[0m ($mode) ======" + + g++ -std=c++11 -pedantic -g -std=c++11 -pedantic -DCNAME="$circuit" $type.c ../test_circuits/mac/mac_$mode.c -o tmp.exe + if ./tmp.exe ; then + echo -e "[\e[32mok\e[0m]" + else + echo -e "[\e[31mfail\e[0m]" + valid=0 + fi + done +} + + + +test_circuit_mac "mac" + + + +if [ $valid -eq 1 ]; then + echo "all tests passed" + exit 0 +else + echo "some of tests failed" + exit 1 +fi