Ejemplo n.º 1
0
    def update_constants_for_synthesis(self, constant_set):
        # Join the values in constant_set to get constant_array in sketch.
        new_constant_set_str = '{' + ','.join(constant_set) + '}'

        # Use string format to create constant_arr_def_
        self.sketch_code_generator.constant_arr_def_ = \
            'int[{}]'.format(str(len(constant_set))) + \
            'constant_vector = {};\n\n'.format(new_constant_set_str)
        self.sketch_code_generator.constant_arr_size_ = get_hole_bit_width(
            len(constant_set))
Ejemplo n.º 2
0
 def generate_mux(self, n, mux_name):
     assert (n >= 1)
     num_bits = get_hole_bit_width(n)
     operand_mux_template = self.jinja2_env_.get_template('mux.j2')
     mux_code = operand_mux_template.render(
         mux_name=mux_name,
         operand_list=['input' + str(i) for i in range(0, n)],
         arg_list=['int input' + str(i) for i in range(0, n)],
         num_operands=n)
     self.add_hole(mux_name + '_ctrl', num_bits)
     return mux_code
Ejemplo n.º 3
0
    def __init__(self, sketch_name, num_phv_containers, num_state_groups,
                 num_alus_per_stage, num_pipeline_stages, num_fields_in_prog,
                 output_packet_fields, output_state_groups,
                 jinja2_env, stateful_alu_filename,
                 stateless_alu_filename, constant_set, group_size,
                 synthesized_allocation, input_packet_fields, target_tofino):
        self.sketch_name_ = sketch_name
        self.total_hole_bits_ = 0
        self.hole_names_ = []
        self.hole_preamble_ = ''
        self.hole_arguments_ = []
        self.holes_ = []
        self.asserts_ = ''
        self.constraints_ = []
        self.num_phv_containers_ = num_phv_containers
        self.num_pipeline_stages_ = num_pipeline_stages
        self.num_state_groups_ = num_state_groups
        self.num_alus_per_stage_ = num_alus_per_stage
        self.num_fields_in_prog_ = num_fields_in_prog
        self.output_packet_fields_ = output_packet_fields
        self.output_state_groups_ = output_state_groups
        self.jinja2_env_ = jinja2_env
        self.jinja2_env_.filters['add_prefix_suffix'] = add_prefix_suffix
        self.stateful_alu_filename_ = stateful_alu_filename
        self.stateless_alu_filename_ = stateless_alu_filename
        self.group_size_ = group_size
        # self.constant_arr_def_ will be the form like
        # int constant_vector[4] = {0,1,2,3};

        constant_set_str = '{' + ','.join(constant_set) + '}'
        self.constant_arr_def_ = 'int[' + \
            str(len(constant_set)) + \
            '] constant_vector = ' + \
            constant_set_str + \
            ';\n\n'
        self.constant_arr_size_ = get_hole_bit_width(len(constant_set))
        self.num_operands_to_stateful_alu_ = 0
        self.num_state_slots_ = 0
        self.synthesized_allocation_ = synthesized_allocation
        self.input_packet_fields_ = input_packet_fields
        self.target_tofino_ = target_tofino
Ejemplo n.º 4
0
 def find_opcode_bits(self):
     with open(self.alu_filename) as f:
         first_line = f.readline()
         prog = re.compile(r'// Max value of opcode is (\d+)')
         result = int(prog.match(first_line).groups(0)[0])
         return get_hole_bit_width(result + 1)
Ejemplo n.º 5
0
    def generate_output_muxes(self):
        # Note: We are generating a mux that takes as input all virtual
        # stateful ALUs + corresponding stateless ALU The number of virtual
        # stateful ALUs is more or less than the physical stateful ALUs because
        # it equals the number of state variables in the original spec, but
        # this doesn't affect correctness because we enforce that the total
        # number of active virtual stateful ALUs is within the physical limit.
        # It also doesn't affect the correctness of modeling the output mux
        # because the virtual output mux setting can be translated into the
        # physical output mux setting during post processing.
        ret = ''
        if self.target_tofino_:
            for i in range(self.num_pipeline_stages_):
                for k in range(self.num_phv_containers_):
                    self.add_hole(self.sketch_name_ +
                                  '_stateless_alu_'
                                  + str(i) + '_' + str(k) + '_demux_ctrl', 1)
            for i in range(self.num_pipeline_stages_):
                for k in range(self.num_state_groups_):
                    self.add_hole(self.sketch_name_ +
                                  '_stateful_alu_'
                                  + str(i) + '_' + str(k) + '_demux_ctrl',
                                  get_hole_bit_width(self.num_phv_containers_))

            # Generate assert for demux for every phv container j
            # i.e assert(
            # ((stateless_demux_i_j == 1) +
            # sum_(k) ((stateful_demux_i_k == 0 && salu_config_i_k == 1))
            # == 1)
            # In English, PHV container j is fed by exactly
            # stateless ALU j or exactly one of the active stateful ALUs,
            # but not both
            for i in range(self.num_pipeline_stages_):
                for j in range(self.num_phv_containers_):
                    # TODO: maybe we need to specially
                    # consider the case j=self.num_phv_containers_ - 1
                    assert_predicate = '(('
                    assert_predicate += '(' + self.sketch_name_ + \
                                        '_stateless_alu_' + str(i) +\
                                        '_' + str(j) + '_demux_ctrl' + \
                                        ' == 1 ) +'
                    for k in range(self.num_state_groups_):
                        assert_predicate += '((' + self.sketch_name_ + \
                                            '_stateful_alu_' + \
                                            str(i) + \
                                            '_' + str(k) + '_demux_ctrl' + \
                                            ' == ' + str(j) + ')  && (' + \
                                            self.sketch_name_ + '_' + \
                                            'salu_config_' + \
                                            str(i) + '_' + \
                            str(k) + '== 1)) + '
                    assert_predicate += ' 0) == 1)'
                    self.add_assert(assert_predicate)
        else:
            for i in range(self.num_pipeline_stages_):
                for k in range(self.num_phv_containers_):
                    # synthesized_allocation we give num_phv_containers virtual
                    # stateful alus per stage
                    if self.synthesized_allocation_:
                        ret += self.generate_mux(
                            self.num_phv_containers_ * self.num_state_slots_
                            + 1,
                            self.sketch_name_ + '_output_mux_phv_' +
                            str(i) + '_' + str(k)) + '\n'
                    else:
                        ret += self.generate_mux(
                            self.num_state_groups_ * self.num_state_slots_ + 1,
                            self.sketch_name_ + '_output_mux_phv_' +
                            str(i) + '_' + str(k)) + '\n'
        return ret
Ejemplo n.º 6
0
 def test_success(self):
     self.assertEqual(1, get_hole_bit_width(2))
     self.assertEqual(3, get_hole_bit_width(5))
     self.assertEqual(4, get_hole_bit_width(11))