예제 #1
0
    def __init__(self,
                 a: Wire = Wire(name="a"),
                 b: Wire = Wire(name="b"),
                 c: Wire = Wire(name="cin"),
                 prefix: str = "fa"):
        super().__init__(a, b, c, prefix)
        # 2 wires for component's bus output (sum, cout)
        self.out = Bus(self.prefix + "_out", 2)

        # PG logic
        propagate_xor = XorGate(a,
                                b,
                                prefix=self.prefix + "_xor" +
                                str(self.get_instance_num(cls=XorGate)),
                                parent_component=self)
        self.add_component(propagate_xor)
        generate_and = AndGate(a,
                               b,
                               prefix=self.prefix + "_and" +
                               str(self.get_instance_num(cls=AndGate)),
                               parent_component=self)
        self.add_component(generate_and)

        # Sum
        # XOR gate for calculation of 1-bit sum
        obj_xor = XorGate(propagate_xor.out,
                          c,
                          prefix=self.prefix + "_xor" +
                          str(self.get_instance_num(cls=XorGate)),
                          outid=0,
                          parent_component=self)
        self.add_component(obj_xor)
        self.out.connect(0, obj_xor.out)

        # Cout
        # AND gate for calculation of 1-bit cout
        obj_and = AndGate(propagate_xor.out,
                          c,
                          prefix=self.prefix + "_and" +
                          str(self.get_instance_num(cls=AndGate)),
                          parent_component=self)
        self.add_component(obj_and)

        obj_or = OrGate(generate_and.out,
                        obj_and.out,
                        prefix=self.prefix + "_or" +
                        str(self.get_instance_num(cls=OrGate)),
                        outid=1,
                        parent_component=self)
        self.add_component(obj_or)

        self.out.connect(1, obj_or.out)
    def __init__(self,
                 a: Wire = Wire(name="a"),
                 b: Wire = Wire(name="b"),
                 prefix: str = "pg_logic"):
        super().__init__(a, b, prefix)
        # 3 wires for component's bus output (propagate, generate, sum)
        self.out = Bus(self.prefix + "_out", 3)

        # PG logic
        propagate_or = OrGate(a,
                              b,
                              prefix=self.prefix + "_or" +
                              str(self.get_instance_num(cls=OrGate)),
                              outid=0,
                              parent_component=self)
        self.add_component(propagate_or)
        generate_and = AndGate(a,
                               b,
                               prefix=self.prefix + "_and" +
                               str(self.get_instance_num(cls=AndGate)),
                               outid=1,
                               parent_component=self)
        self.add_component(generate_and)
        sum_xor = XorGate(a,
                          b,
                          prefix=self.prefix + "_xor" +
                          str(self.get_instance_num(cls=XorGate)),
                          outid=2,
                          parent_component=self)
        self.add_component(sum_xor)

        self.out.connect(0, propagate_or.out)
        self.out.connect(1, generate_and.out)
        self.out.connect(2, sum_xor.out)
    def __init__(self,
                 a: Wire = Wire(name="a"),
                 b: Wire = Wire(name="b"),
                 prefix: str = "hs"):
        super().__init__(a, b, prefix)
        # 2 wires for component's bus output (difference, bout)
        self.out = Bus(self.prefix + "_out", 2)

        # Difference
        # XOR gate for calculation of 1-bit difference
        difference_xor = XorGate(a=self.a,
                                 b=self.b,
                                 prefix=self.prefix + "_xor" +
                                 str(self.get_instance_num(cls=XorGate)),
                                 outid=0,
                                 parent_component=self)
        self.add_component(difference_xor)
        self.out.connect(0, difference_xor.out)

        # Bout
        # NOT and AND gates for calculation of 1-bit borrow out
        not_obj = NotGate(a=self.a,
                          prefix=self.prefix + "_not" +
                          str(self.get_instance_num(cls=NotGate)),
                          parent_component=self)
        self.add_component(not_obj)

        borrow_and = AndGate(a=not_obj.out,
                             b=self.b,
                             prefix=self.prefix + "_xor" +
                             str(self.get_instance_num(cls=XorGate)),
                             outid=1,
                             parent_component=self)
        self.add_component(borrow_and)
        self.out.connect(1, borrow_and.out)
예제 #4
0
    def __init__(self,
                 a: Wire = Wire(name="d0"),
                 b: Wire = Wire(name="d1"),
                 c: Wire = Wire(name="sel"),
                 prefix: str = "mux2to1"):
        super().__init__(a, b, c, prefix)
        # Represents select signal (self.c naming for proper unified generation)
        self.c = c
        # 1 wire for component's output bus
        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)

        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)

        xor_obj = XorGate(a=self.get_previous_component(3).out,
                          b=self.get_previous_component().out,
                          prefix=self.prefix + "_xor" +
                          str(self.get_instance_num(cls=XorGate)),
                          parent_component=self)
        self.add_component(xor_obj)

        # Connection of MUX output wire
        self.out.connect(0, xor_obj.out)
    def add_column_wires(self, column: list, column_index: int, signed: bool):
        """Fills circuit's partial product column with corresponding bit pairs.

        Args:
            column (list): List representing column of partial product bits.
            column_index (int): Index of partial products column.
            signed (bool): Specify whether pp columns bit pairs should perform signed multiplication or not.

        Returns:
            list: Updated column list containing corresponding number of input bit pairs to form proper pp column.
        """
        # Adding neccessary number of lists (based on number of bits in the column – stored in `column[0]`)
        # to column that each represent individual bit pairs for described column (these bit pairs are then combined in AND/NAND gates)
        [column.append([]) for _ in range(column[0])]
        # Filling column bit pair lists with appropriate bits
        if column_index <= self.N-1:
            [column[column[0]-index].append(self.a.get_wire(index)) for index in range(0, column[0])]
            [column[index+1].append(self.b.get_wire(index)) for index in range(0, column[0])]
        else:
            [column[self.a.N-index].append(self.a.get_wire(index)) for index in range(self.a.N-1, self.a.N-column[0]-1, -1)]
            [column[index-(self.a.N-1-column[0])].append(self.b.get_wire(index)) for index in range(self.a.N-column[0], self.a.N)]

        # Converting unsigned column pp bit pair lists into AND gates
        if signed is False:
            column[1:] = [AndGate(a=column[i][0], b=column[i][1], prefix=self.prefix+'_and_'+str(column[i][0].index)+'_'+str(column[i][1].index), parent_component=self) for i in range(1, len(column))]
        # Converting signed column pp bit pair lists into AND/NAND gates (based on Baugh-Wooley multiplication algorithm)
        else:
            # First half of partial product columns contains only AND gates
            if column_index < self.N-1 or column_index == self.out.N-2:
                column[1:] = [AndGate(a=column[i][0], b=column[i][1], prefix=self.prefix+'_and_'+str(column[i][0].index)+'_'+str(column[i][1].index), parent_component=self) for i in range(1, len(column))]
            # Second half of partial product columns contains NAND/AND gates
            else:
                column[1] = NandGate(a=column[1][0], b=column[1][1], prefix=self.prefix+'_nand_'+str(column[1][0].index)+'_'+str(column[1][1].index), parent_component=self)
                column[-1] = NandGate(a=column[-1][0], b=column[-1][1], prefix=self.prefix+'_nand_'+str(column[-1][0].index)+'_'+str(column[-1][1].index), parent_component=self)
                if len(column[2:-1]) != 0:
                    column[2:-1] = [AndGate(a=column[i][0], b=column[i][1], prefix=self.prefix+'_and_'+str(column[i][0].index)+'_'+str(column[i][1].index), parent_component=self) for i in range(2, len(column)-1)]

        return column
    def __init__(self, a: Bus, b: Bus, prefix: str = "u_pg_rca"):
        super().__init__()
        self.N = max(a.N, b.N)
        self.prefix = prefix
        self.a = Bus(prefix=a.prefix, wires_list=a.bus)
        self.b = Bus(prefix=b.prefix, wires_list=b.bus)

        # Bus sign extension in case buses have different lengths
        self.a.bus_extend(N=self.N, prefix=a.prefix)
        self.b.bus_extend(N=self.N, prefix=b.prefix)

        # Output wires for N sum bits and additional cout bit
        self.out = Bus(self.prefix + "_out", self.N + 1)

        # Gradual addition of 1-bit adder components
        for input_index in range(self.N):
            if input_index == 0:
                # First full adder with connected constant wire with value 0 as cin 0
                obj_pg_fa = FullAdderPG(self.a.get_wire(input_index),
                                        self.b.get_wire(input_index),
                                        ConstantWireValue0(),
                                        prefix=self.prefix + "_pg_fa" +
                                        str(input_index))
            else:
                obj_pg_fa = FullAdderPG(self.a.get_wire(input_index),
                                        self.b.get_wire(input_index),
                                        self.get_previous_component().out,
                                        prefix=self.prefix + "_pg_fa" +
                                        str(input_index))

            self.add_component(obj_pg_fa)
            self.out.connect(input_index, obj_pg_fa.get_sum_wire())

            obj_and = AndGate(
                self.get_previous_component().c,
                self.get_previous_component().get_propagate_wire(),
                prefix=self.prefix + "_and" + str(input_index),
                parent_component=self)
            obj_or = OrGate(obj_and.out,
                            self.get_previous_component().get_generate_wire(),
                            prefix=self.prefix + "_or" + str(input_index),
                            parent_component=self)
            self.add_component(obj_and)
            self.add_component(obj_or)

            # Connecting last output bit to last cout
            if input_index == (self.N - 1):
                self.out.connect(self.N, obj_or.out)
    def __init__(self,
                 a: Bus,
                 b: Bus,
                 cla_block_size: int = 4,
                 prefix: str = "u_cla"):
        super().__init__()
        self.N = max(a.N, b.N)
        self.prefix = prefix
        self.a = Bus(prefix=a.prefix, wires_list=a.bus)
        self.b = Bus(prefix=b.prefix, wires_list=b.bus)

        # Bus sign extension in case buses have different lengths
        self.a.bus_extend(N=self.N, prefix=a.prefix)
        self.b.bus_extend(N=self.N, prefix=b.prefix)

        # Output wires for N sum bits and additional cout bit
        self.out = Bus(self.prefix + "_out", self.N + 1)

        # To signify current number of blocks and number of bits that remain to be added into function blocks
        N_blocks = 0
        N_wires = self.N
        cin = ConstantWireValue0()

        while N_wires != 0:
            # Lists containing all propagate/generate wires
            self.propagate = []
            self.generate = []
            # Cin0 used as a first generate wire for obtaining next carry bits
            self.generate.append(cin)
            block_size = cla_block_size if N_wires >= cla_block_size else N_wires

            # Gradual addition of propagate/generate logic blocks and AND/OR gates for Cout bits generation, XOR gates for Sum bits generation
            for i in range(block_size):
                pg_block = PGLogicBlock(
                    self.a.get_wire((N_blocks * cla_block_size) + i),
                    self.b.get_wire((N_blocks * cla_block_size) + i),
                    prefix=self.prefix + "_pg_logic" +
                    str(self.get_instance_num(cls=PGLogicBlock)))
                self.propagate.append(pg_block.get_propagate_wire())
                self.generate.append(pg_block.get_generate_wire())
                self.add_component(pg_block)

                if i == 0 and N_blocks == 0:
                    obj_sum_xor = XorGate(
                        pg_block.get_sum_wire(),
                        cin,
                        prefix=self.prefix + "_xor" +
                        str(self.get_instance_num(cls=XorGate)),
                        parent_component=self)
                    self.add_component(obj_sum_xor)
                    self.out.connect(i + (N_blocks * cla_block_size),
                                     obj_sum_xor.out)

                    # Carry propagation calculation
                    obj_and = AndGate(
                        self.propagate[(N_blocks * cla_block_size) + i],
                        self.generate[(N_blocks * cla_block_size) + i],
                        prefix=self.prefix + "_and" +
                        str(self.get_instance_num(cls=AndGate)),
                        parent_component=self)
                    self.add_component(obj_and)

                    # Carry bit generation
                    obj_cout_or = OrGate(
                        pg_block.get_generate_wire(),
                        self.get_previous_component().out,
                        prefix=self.prefix + "_or" + str(
                            self.get_instance_num(cls=OrGate,
                                                  count_disabled_gates=False)),
                        parent_component=self)
                    self.add_component(obj_cout_or)
                else:
                    obj_sum_xor = XorGate(
                        pg_block.get_sum_wire(),
                        self.get_previous_component(2).out,
                        prefix=self.prefix + "_xor" +
                        str(self.get_instance_num(cls=XorGate)),
                        parent_component=self)
                    self.add_component(obj_sum_xor)
                    self.out.connect(i + (N_blocks * cla_block_size),
                                     obj_sum_xor.out)

                    # List of AND gates outputs that are later combined in a multi-bit OR gate
                    composite_or_gates_inputs = []

                    for g_index in range(len(self.generate) - 1):
                        composite_wires = []
                        # Getting a list of wires used for current bit position cout composite AND gate's generation
                        # E.g. for Cout2 = G1 + G0·P1 C0·P0·P1 it gets a list containing [C0,P0,P1] then [G0,P1]
                        composite_wires.append(self.generate[g_index])
                        for p_index in range(
                                len(self.propagate) - 1, g_index - 1, -1):
                            composite_wires.append(self.propagate[p_index])

                        # For each pg pair values algorithmically combine two input AND gates to replace multiple input gates (resolves fan-in issue)
                        pg_wires = Bus(wires_list=composite_wires)
                        multi_bit_and_gate = MultipleInputLogicGate(
                            a=pg_wires,
                            two_input_gate_cls=AndGate,
                            prefix=self.prefix + "_and",
                            parent_component=self)
                        composite_or_gates_inputs.append(
                            multi_bit_and_gate.out)

                    # Final OR gates cascade using generated AND gates output wires
                    composite_or_wires = Bus(
                        wires_list=composite_or_gates_inputs)
                    multi_bit_or_gate = MultipleInputLogicGate(
                        a=composite_or_wires,
                        two_input_gate_cls=OrGate,
                        prefix=self.prefix + "_or",
                        parent_component=self)

                    # Carry bit generation
                    obj_cout_or = OrGate(
                        pg_block.get_generate_wire(),
                        multi_bit_or_gate.out,
                        prefix=self.prefix + "_or" + str(
                            self.get_instance_num(cls=OrGate,
                                                  count_disabled_gates=False)),
                        parent_component=self)
                    self.add_component(obj_cout_or)

            # Updating cin for the the next bypass block
            # Also updating cout value which is used as cin for the first adder of the next block
            cin = obj_cout_or.out

            N_wires -= block_size
            N_blocks += 1

        # Connection of final Cout
        self.out.connect(self.N, cin)
예제 #8
0
    def __init__(self,
                 a: Wire = Wire(name="a"),
                 b: Wire = Wire(name="b"),
                 c: Wire = Wire(name="bin"),
                 prefix: str = "fs"):
        super().__init__(a, b, c, prefix)
        # 2 wires for component's bus output (difference, bout)
        self.out = Bus(self.prefix + "_out", 2)

        # Difference
        xor_obj = XorGate(a=self.a,
                          b=self.b,
                          prefix=self.prefix + "_xor" +
                          str(self.get_instance_num(cls=XorGate)),
                          parent_component=self)
        self.add_component(xor_obj)

        not_obj = NotGate(a=self.a,
                          prefix=self.prefix + "_not" +
                          str(self.get_instance_num(cls=NotGate)),
                          parent_component=self)
        self.add_component(not_obj)

        and_obj = AndGate(a=not_obj.out,
                          b=self.b,
                          prefix=self.prefix + "_and" +
                          str(self.get_instance_num(cls=AndGate)),
                          parent_component=self)
        self.add_component(and_obj)

        difference_xor = XorGate(a=self.c,
                                 b=xor_obj.out,
                                 prefix=self.prefix + "_xor" +
                                 str(self.get_instance_num(cls=XorGate)),
                                 outid=0,
                                 parent_component=self)
        self.add_component(difference_xor)
        self.out.connect(0, difference_xor.out)

        # Borrow out
        not_obj = NotGate(a=xor_obj.out,
                          prefix=self.prefix + "_not" +
                          str(self.get_instance_num(cls=NotGate)),
                          parent_component=self)
        self.add_component(not_obj)

        and_obj = AndGate(a=not_obj.out,
                          b=self.c,
                          prefix=self.prefix + "_and" +
                          str(self.get_instance_num(cls=AndGate)),
                          parent_component=self)
        self.add_component(and_obj)

        borrow_out_or = OrGate(a=and_obj.out,
                               b=self.get_previous_component(4).out,
                               prefix=self.prefix + "_or" +
                               str(self.get_instance_num(cls=OrGate)),
                               outid=1,
                               parent_component=self)
        self.add_component(borrow_out_or)
        self.out.connect(1, borrow_out_or.out)
    def __init__(self, a: Bus, b: Bus, prefix: str = "u_arrmul"):
        super().__init__()
        self.N = max(a.N, b.N)
        self.prefix = prefix
        self.a = Bus(prefix=a.prefix, wires_list=a.bus)
        self.b = Bus(prefix=b.prefix, wires_list=b.bus)

        # Bus sign extension in case buses have different lengths
        self.a.bus_extend(N=self.N, prefix=a.prefix)
        self.b.bus_extend(N=self.N, prefix=b.prefix)

        # Output wires for multiplication product
        self.out = Bus(self.prefix + "_out", self.N * 2)

        # Gradual generation of partial products
        for b_multiplier_index in range(self.N):
            for a_multiplicand_index in range(self.N):
                # AND gates generation for calculation of partial products
                obj_and = AndGate(self.a.get_wire(a_multiplicand_index),
                                  self.b.get_wire(b_multiplier_index),
                                  prefix=self.prefix + "_and" +
                                  str(a_multiplicand_index) + "_" +
                                  str(b_multiplier_index))
                self.add_component(obj_and)

                if b_multiplier_index != 0:
                    previous_product = self.components[
                        a_multiplicand_index +
                        b_multiplier_index].out if b_multiplier_index == 1 else self.get_previous_partial_product(
                            a_index=a_multiplicand_index,
                            b_index=b_multiplier_index)
                    # HA generation for first 1-bit adder in each row starting from the second one
                    if a_multiplicand_index == 0:
                        obj_adder = HalfAdder(
                            self.get_previous_component().out,
                            previous_product,
                            prefix=self.prefix + "_ha" +
                            str(a_multiplicand_index) + "_" +
                            str(b_multiplier_index))
                        self.add_component(obj_adder)
                        # Product generation
                        self.out.connect(b_multiplier_index,
                                         obj_adder.get_sum_wire())

                    # HA generation, last 1-bit adder in second row
                    elif a_multiplicand_index == self.N - 1 and b_multiplier_index == 1:
                        obj_adder = HalfAdder(
                            self.get_previous_component().out,
                            self.get_previous_component(
                                number=2).get_carry_wire(),
                            prefix=self.prefix + "_ha" +
                            str(a_multiplicand_index) + "_" +
                            str(b_multiplier_index))
                        self.add_component(obj_adder)

                    # FA generation
                    else:
                        obj_adder = FullAdder(
                            self.get_previous_component().out,
                            previous_product,
                            self.get_previous_component(
                                number=2).get_carry_wire(),
                            prefix=self.prefix + "_fa" +
                            str(a_multiplicand_index) + "_" +
                            str(b_multiplier_index))
                        self.add_component(obj_adder)

                # PRODUCT GENERATION
                if a_multiplicand_index == 0 and b_multiplier_index == 0:
                    self.out.connect(a_multiplicand_index, obj_and.out)

                    # 1 bit multiplier case
                    if a_multiplicand_index == self.N - 1:
                        self.out.connect(a_multiplicand_index + 1,
                                         ConstantWireValue0)

                elif b_multiplier_index == self.N - 1:
                    self.out.connect(b_multiplier_index + a_multiplicand_index,
                                     obj_adder.get_sum_wire())

                    if a_multiplicand_index == self.N - 1:
                        self.out.connect(self.out.N - 1,
                                         obj_adder.get_carry_wire())
    def __init__(self, a: Bus, b: Bus, prefix: str = "s_arrmul"):
        super().__init__()
        self.c_data_type = "int64_t"
        self.N = max(a.N, b.N)
        self.prefix = prefix
        self.a = Bus(prefix=a.prefix, wires_list=a.bus)
        self.b = Bus(prefix=b.prefix, wires_list=b.bus)

        # Bus sign extension in case buses have different lengths
        self.a.bus_extend(N=self.N, prefix=a.prefix)
        self.b.bus_extend(N=self.N, prefix=b.prefix)

        # Output wires for multiplication product
        self.out = Bus(self.prefix + "_out", self.N * 2)

        # Gradual generation of partial products
        for b_multiplier_index in range(self.N):
            for a_multiplicand_index in range(self.N):
                # AND and NAND gates generation for calculation of partial products and sign extension
                if (b_multiplier_index == self.N - 1
                        and a_multiplicand_index != self.N - 1) or (
                            b_multiplier_index != self.N - 1
                            and a_multiplicand_index == self.N - 1):
                    obj_nand = NandGate(self.a.get_wire(a_multiplicand_index),
                                        self.b.get_wire(b_multiplier_index),
                                        prefix=self.prefix + "_nand" +
                                        str(a_multiplicand_index) + "_" +
                                        str(b_multiplier_index),
                                        parent_component=self)
                    self.add_component(obj_nand)
                else:
                    obj_and = AndGate(self.a.get_wire(a_multiplicand_index),
                                      self.b.get_wire(b_multiplier_index),
                                      prefix=self.prefix + "_and" +
                                      str(a_multiplicand_index) + "_" +
                                      str(b_multiplier_index),
                                      parent_component=self)
                    self.add_component(obj_and)

                if b_multiplier_index != 0:
                    previous_product = self.components[
                        a_multiplicand_index +
                        b_multiplier_index].out if b_multiplier_index == 1 else self.get_previous_partial_product(
                            a_index=a_multiplicand_index,
                            b_index=b_multiplier_index)
                    # HA generation for first 1-bit adder in each row starting from the second one
                    if a_multiplicand_index == 0:
                        obj_adder = HalfAdder(
                            self.get_previous_component().out,
                            previous_product,
                            prefix=self.prefix + "_ha" +
                            str(a_multiplicand_index) + "_" +
                            str(b_multiplier_index))
                        self.add_component(obj_adder)
                        # Product generation
                        self.out.connect(b_multiplier_index,
                                         obj_adder.get_sum_wire())

                    # FA generation
                    else:
                        # Constant wire with value 1 used at the last FA in second row (as one of its inputs) for signed multiplication (based on Baugh Wooley algorithm)
                        if a_multiplicand_index == self.N - 1 and b_multiplier_index == 1:
                            previous_product = ConstantWireValue1()

                        obj_adder = FullAdder(
                            self.get_previous_component().out,
                            previous_product,
                            self.get_previous_component(
                                number=2).get_carry_wire(),
                            prefix=self.prefix + "_fa" +
                            str(a_multiplicand_index) + "_" +
                            str(b_multiplier_index))
                        self.add_component(obj_adder)

                # PRODUCT GENERATION
                if a_multiplicand_index == 0 and b_multiplier_index == 0:
                    self.out.connect(a_multiplicand_index, obj_and.out)

                    # 1 bit multiplier case
                    if a_multiplicand_index == self.N - 1:
                        obj_nor = NorGate(ConstantWireValue1(),
                                          self.get_previous_component().out,
                                          prefix=self.prefix +
                                          "_nor_zero_extend",
                                          parent_component=self)
                        self.add_component(obj_nor)

                        self.out.connect(a_multiplicand_index + 1, obj_nor.out)

                elif b_multiplier_index == self.N - 1:
                    self.out.connect(b_multiplier_index + a_multiplicand_index,
                                     obj_adder.get_sum_wire())

                    if a_multiplicand_index == self.N - 1:
                        obj_xor = XorGate(
                            self.get_previous_component().get_carry_wire(),
                            ConstantWireValue1(),
                            prefix=self.prefix + "_xor" +
                            str(a_multiplicand_index + 1) + "_" +
                            str(b_multiplier_index),
                            parent_component=self)
                        self.add_component(obj_xor)

                        self.out.connect(self.out.N - 1, obj_xor.out)