/*---------------------------------------------------------------------- * (function: partial_map_node) *--------------------------------------------------------------------*/ void partial_map_node(nnode_t *node, short traverse_number, netlist_t *netlist) { switch (node->type) { case BITWISE_NOT: instantiate_not_logic(node, traverse_number, netlist); break; case BUF_NODE: instantiate_buffer(node, traverse_number, netlist); break; case BITWISE_AND: case BITWISE_OR: case BITWISE_NAND: case BITWISE_NOR: case BITWISE_XNOR: case BITWISE_XOR: if (node->num_input_port_sizes == 2) { instantiate_bitwise_logic(node, node->type, traverse_number, netlist); } else if (node->num_input_port_sizes == 1) { instantiate_bitwise_reduction(node, node->type, traverse_number, netlist); } else oassert(FALSE); break; case LOGICAL_OR: case LOGICAL_AND: case LOGICAL_NOR: case LOGICAL_NAND: case LOGICAL_XOR: case LOGICAL_XNOR: if (node->num_input_port_sizes == 2) { instantiate_logical_logic(node, node->type, traverse_number, netlist); } break; case LOGICAL_NOT: /* don't need to do anything since this is a reduction */ break; case ADD: instantiate_add_w_carry(node, traverse_number, netlist); break; case MINUS: if (node->num_input_port_sizes == 2) { instantiate_sub_w_carry(node, traverse_number, netlist); } else if (node->num_input_port_sizes == 1) { instantiate_unary_sub(node, traverse_number, netlist); } else oassert(FALSE); break; case LOGICAL_EQUAL: case NOT_EQUAL: instantiate_EQUAL(node, node->type, traverse_number, netlist); break; case GTE: case LTE: instantiate_GE(node, node->type, traverse_number, netlist); break; case GT: case LT: instantiate_GT(node, node->type, traverse_number, netlist); break; case SL: case SR: instantiate_shift_left_or_right(node, node->type, traverse_number, netlist); break; case MULTI_PORT_MUX: instantiate_multi_port_mux(node, traverse_number, netlist); break; case MULTIPLY: #ifdef VPR6 if (hard_multipliers != NULL) { if ((node->input_port_sizes[0] + node->input_port_sizes[1]) > min_mult) instantiate_hard_multiplier(node, traverse_number, netlist); } else #endif instantiate_simple_soft_multiplier(node, traverse_number, netlist); break; case MEMORY: case HARD_IP: #ifdef VPR6 instantiate_hard_block(node, traverse_number, netlist); #endif break; case ADDER_FUNC: case CARRY_FUNC: case MUX_2: case INPUT_NODE: case CLOCK_NODE: case OUTPUT_NODE: case GND_NODE: case VCC_NODE: case FF_NODE: case PAD_NODE: /* some nodes already in the form that is mapable */ break; case CASE_EQUAL: case CASE_NOT_EQUAL: case DIVIDE: case MODULO: default: oassert(FALSE); break; } }
/*--------------------------------------------------------------------------- * (function: instantiate_simple_soft_multiplier ) * Sample 4x4 multiplier to help understand logic. * * a3 a2 a1 a0 * b3 b2 b1 b0 * --------------------------- * c03 c02 c01 c00 * + c13 c12 c11 c10 * ----------------------------------- * r14 r13 r12 r11 r10 * + c23 c22 c21 c20 * ----------------------------------- * r24 r23 r22 r21 r20 * + c33 c32 c31 c30 * ------------------------------------ * o7 o6 o5 o4 o3 o2 o1 o0 * * In the first case will be c01 *-------------------------------------------------------------------------*/ void instantiate_simple_soft_multiplier(nnode_t *node, short mark, netlist_t *netlist) { int width_a; int width_b; int width; int multiplier_width; int multiplicand_width; nnode_t **adders_for_partial_products; nnode_t ***partial_products; int multiplicand_offset_index; int multiplier_offset_index; int current_index; int i, j; /* need for an carry-ripple-adder for each of the bits of port B. */ /* good question of which is better to put on the bottom of multiplier. Larger means more smaller adds, or small is * less large adds */ oassert(node->num_output_pins > 0); oassert(node->num_input_pins > 0); oassert(node->num_input_port_sizes == 2); oassert(node->num_output_port_sizes == 1); width_a = node->input_port_sizes[0]; width_b = node->input_port_sizes[1]; width = node->output_port_sizes[0]; multiplicand_width = width_b; multiplier_width = width_a; /* offset is related to which multport is chosen as the multiplicand */ multiplicand_offset_index = width_a; multiplier_offset_index = 0; adders_for_partial_products = (nnode_t**)malloc(sizeof(nnode_t*)*multiplicand_width-1); /* need to generate partial products for each bit in width B. */ partial_products = (nnode_t***)malloc(sizeof(nnode_t**)*multiplicand_width); /* generate the AND partial products */ for (i = 0; i < multiplicand_width; i++) { /* create the memory for each AND gate needed for the levels of partial products */ partial_products[i] = (nnode_t**)malloc(sizeof(nnode_t*)*multiplier_width); if (i < multiplicand_width - 1) { adders_for_partial_products[i] = make_2port_gate(ADD, multiplier_width+1, multiplier_width+1, multiplier_width+1, node, mark); } for (j = 0; j < multiplier_width; j++) { /* create each one of the partial products */ partial_products[i][j] = make_1port_logic_gate(LOGICAL_AND, 2, node, mark); } } /* generate the coneections to the AND gates */ for (i = 0; i < multiplicand_width; i++) { for (j = 0; j < multiplier_width; j++) { /* hookup the input of B to each AND gate */ if (j == 0) { /* IF - this is the first time we are mapping multiplicand port then can remap */ remap_pin_to_new_node(node->input_pins[i+multiplicand_offset_index], partial_products[i][j], 0); } else { /* ELSE - this needs to be a new ouput of the multiplicand port */ add_input_pin_to_node(partial_products[i][j], copy_input_npin(partial_products[i][0]->input_pins[0]), 0); } /* hookup the input of the multiplier to each AND gate */ if (i == 0) { /* IF - this is the first time we are mapping multiplier port then can remap */ remap_pin_to_new_node(node->input_pins[j+multiplier_offset_index], partial_products[i][j], 1); } else { /* ELSE - this needs to be a new ouput of the multiplier port */ add_input_pin_to_node(partial_products[i][j], copy_input_npin(partial_products[0][j]->input_pins[1]), 1); } } } /* hookup each of the adders */ for (i = 0; i < multiplicand_width-1; i++) // -1 since the first stage is a combo of partial products while all others are part of tree { for (j = 0; j < multiplier_width+1; j++) // +1 since adders are one greater than multwidth to pass carry { /* join to port 1 of the add one of the partial products. */ if (i == 0) { /* IF - this is the first addition row, then adding two sets of partial products and first set is from the c0* */ if (j < multiplier_width-1) { /* IF - we just take an element of the first list c[0][j+1]. */ connect_nodes(partial_products[i][j+1], 0, adders_for_partial_products[i], j); } else { /* ELSE - this is the last input to the first adder, then we pass in 0 since no carry yet */ add_input_pin_to_node(adders_for_partial_products[i], get_zero_pin(netlist), j); } } else if (j < multiplier_width) { /* ELSE - this is the standard situation when we need to hookup this adder with a previous adder, r[i-1][j+1] */ connect_nodes(adders_for_partial_products[i-1], j+1, adders_for_partial_products[i], j); } else { add_input_pin_to_node(adders_for_partial_products[i], get_zero_pin(netlist), j); } if (j < multiplier_width) { /* IF - this is not most significant bit then just add current partial product */ connect_nodes(partial_products[i+1][j], 0, adders_for_partial_products[i], j+multiplier_width+1); } else { add_input_pin_to_node(adders_for_partial_products[i], get_zero_pin(netlist), j+multiplier_width+1); } } } current_index = 0; /* hookup the outputs */ for (i = 0; i < width; i++) { if (multiplicand_width == 1) { // this is undealt with error_message(1,-1,-1,"Cannot create soft multiplier with multiplicand width of 1.\n"); } else if (i == 0) { /* IF - this is the LSbit, then we use a pass through from the partial product */ remap_pin_to_new_node(node->output_pins[i], partial_products[0][0], 0); } else if (i < multiplicand_width - 1) { /* ELSE IF - these are the middle values that come from the LSbit of partial adders */ remap_pin_to_new_node(node->output_pins[i], adders_for_partial_products[i-1], 0); } else { /* ELSE - the final outputs are straight from the outputs of the last adder */ remap_pin_to_new_node(node->output_pins[i], adders_for_partial_products[multiplicand_width-2], current_index); current_index++; } } /* soft map the adders if they need to be mapped */ for (i = 0; i < multiplicand_width - 1; i++) { instantiate_add_w_carry(adders_for_partial_products[i], mark, netlist); } /* Cleanup everything */ if (adders_for_partial_products != NULL) { free(adders_for_partial_products); } /* generate the AND partial products */ for (i = 0; i < multiplicand_width; i++) { /* create the memory for each AND gate needed for the levels of partial products */ if (partial_products[i] != NULL) { free(partial_products[i]); } } if (partial_products != NULL) { free(partial_products); } }