| /* |
| Permission is hereby granted, free of charge, to any person |
| obtaining a copy of this software and associated documentation |
| files (the "Software"), to deal in the Software without |
| restriction, including without limitation the rights to use, |
| copy, modify, merge, publish, distribute, sublicense, and/or sell |
| copies of the Software, and to permit persons to whom the |
| Software is furnished to do so, subject to the following |
| conditions: |
| |
| The above copyright notice and this permission notice shall be |
| included in all copies or substantial portions of the Software. |
| |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
| OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <stdarg.h> |
| #include "types.h" |
| #include "globals.h" |
| #include "netlist_utils.h" |
| #include "odin_util.h" |
| #include "node_creation_library.h" |
| #include "util.h" |
| |
| long unique_node_name_id = 0; |
| |
| /*----------------------------------------------------------------------- |
| * (function: get_a_pad_pin) |
| * this allows us to attach to the constant netlist driving hb_pad |
| *---------------------------------------------------------------------*/ |
| npin_t *get_a_pad_pin(netlist_t *netlist) |
| { |
| npin_t *pad_fanout_pin = allocate_npin(); |
| pad_fanout_pin->name = pad_string; |
| add_a_fanout_pin_to_net(netlist->pad_net, pad_fanout_pin); |
| return pad_fanout_pin; |
| } |
| |
| /*----------------------------------------------------------------------- |
| * (function: get_a_zero_pin) |
| * this allows us to attach to the constant netlist driving zero |
| *---------------------------------------------------------------------*/ |
| npin_t *get_a_zero_pin(netlist_t *netlist) |
| { |
| npin_t *zero_fanout_pin = allocate_npin(); |
| zero_fanout_pin->name = zero_string; |
| add_a_fanout_pin_to_net(netlist->zero_net, zero_fanout_pin); |
| return zero_fanout_pin; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: get_a_one_pin) |
| * this allows us to attach to the constant netlist driving one |
| *-------------------------------------------------------------------------------------------*/ |
| npin_t *get_a_one_pin(netlist_t *netlist) |
| { |
| npin_t *one_fanout_pin = allocate_npin(); |
| one_fanout_pin->name = one_string; |
| add_a_fanout_pin_to_net(netlist->one_net, one_fanout_pin); |
| return one_fanout_pin; |
| } |
| |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: make_not_gate_with_input) |
| * Creates a not gate and attaches it to the inputs |
| *-------------------------------------------------------------------------------------------*/ |
| nnode_t *make_not_gate_with_input(npin_t *input_pin, nnode_t *node, short mark) |
| { |
| nnode_t *logic_node; |
| |
| logic_node = make_not_gate(node, mark); |
| |
| /* add the input ports as needed */ |
| add_a_input_pin_to_node_spot_idx(logic_node, input_pin, 0); |
| |
| return logic_node; |
| |
| } |
| |
| /*------------------------------------------------------------------------- |
| * (function: make_not_gate) |
| * Just make a not gate |
| *-----------------------------------------------------------------------*/ |
| nnode_t *make_not_gate(nnode_t *node, short mark) |
| { |
| nnode_t *logic_node; |
| |
| logic_node = allocate_nnode(); |
| logic_node->traverse_visited = mark; |
| logic_node->type = LOGICAL_NOT; |
| logic_node->name = node_name(logic_node, node->name); |
| logic_node->related_ast_node = node->related_ast_node; |
| |
| allocate_more_node_input_pins(logic_node, 1); |
| allocate_more_node_output_pins(logic_node, 1); |
| |
| return logic_node; |
| |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: make_1port_gate) |
| * Make a 1 port gate with variable sizes |
| *-------------------------------------------------------------------------------------------*/ |
| nnode_t *make_1port_gate(operation_list type, int width_input, int width_output, nnode_t *node, short mark) |
| { |
| nnode_t *logic_node; |
| |
| logic_node = allocate_nnode(); |
| logic_node->traverse_visited = mark; |
| logic_node->type = type; |
| logic_node->name = node_name(logic_node, node->name); |
| logic_node->related_ast_node = node->related_ast_node; |
| |
| /* add the input ports as needed */ |
| allocate_more_node_input_pins(logic_node, width_input); |
| add_input_port_information(logic_node, width_input); |
| /* add output */ |
| allocate_more_node_output_pins(logic_node, width_output); |
| add_output_port_information(logic_node, width_output); |
| |
| return logic_node; |
| } |
| /*--------------------------------------------------------------------------------------------- |
| * (function: make_1port_logic_gate) |
| * Make a gate with variable sized inputs and 1 output |
| *-------------------------------------------------------------------------------------------*/ |
| nnode_t *make_1port_logic_gate(operation_list type, int width, nnode_t *node, short mark) |
| { |
| nnode_t *logic_node; |
| |
| logic_node = make_1port_gate(type, width, 1, node, mark); |
| |
| return logic_node; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: make_1port_logic_gate_with_inputs) |
| * Make a gate with variable sized inputs, 1 output, and connect to the supplied inputs |
| *-------------------------------------------------------------------------------------------*/ |
| nnode_t *make_1port_logic_gate_with_inputs(operation_list type, int width, signal_list_t *pin_list, nnode_t *node, short mark) |
| { |
| nnode_t *logic_node; |
| int i; |
| |
| logic_node = make_1port_gate(type, width, 1, node, mark); |
| |
| /* hookup all the pins */ |
| for (i = 0; i < width; i++) |
| { |
| add_a_input_pin_to_node_spot_idx(logic_node, pin_list->signal_list[i], i); |
| } |
| |
| return logic_node; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: make_3port_logic_gates) |
| * Make a 3 port gate all variable port widths. |
| *-------------------------------------------------------------------------------------------*/ |
| nnode_t *make_3port_gate(operation_list type, int width_port1, int width_port2, int width_port3, int width_output, nnode_t *node, short mark) |
| { |
| nnode_t *logic_node = allocate_nnode(); |
| logic_node->traverse_visited = mark; |
| logic_node->type = type; |
| logic_node->name = node_name(logic_node, node->name); |
| logic_node->related_ast_node = node->related_ast_node; |
| |
| /* add the input ports as needed */ |
| allocate_more_node_input_pins(logic_node, width_port1); |
| add_input_port_information(logic_node, width_port1); |
| allocate_more_node_input_pins(logic_node, width_port2); |
| add_input_port_information(logic_node, width_port2); |
| allocate_more_node_input_pins(logic_node, width_port3); |
| add_input_port_information(logic_node, width_port3); |
| /* add output */ |
| allocate_more_node_output_pins(logic_node, width_output); |
| add_output_port_information(logic_node, width_output); |
| |
| return logic_node; |
| } |
| |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: make_2port_logic_gates) |
| * Make a 2 port gate with variable sizes. The first port will be input_pins index 0..width_port1. |
| *-------------------------------------------------------------------------------------------*/ |
| nnode_t *make_2port_gate(operation_list type, int width_port1, int width_port2, int width_output, nnode_t *node, short mark) |
| { |
| nnode_t *logic_node = allocate_nnode(); |
| logic_node->traverse_visited = mark; |
| logic_node->type = type; |
| logic_node->name = node_name(logic_node, node->name); |
| logic_node->related_ast_node = node->related_ast_node; |
| |
| /* add the input ports as needed */ |
| allocate_more_node_input_pins(logic_node, width_port1); |
| add_input_port_information(logic_node, width_port1); |
| allocate_more_node_input_pins(logic_node, width_port2); |
| add_input_port_information(logic_node, width_port2); |
| /* add output */ |
| allocate_more_node_output_pins(logic_node, width_output); |
| add_output_port_information(logic_node, width_output); |
| |
| return logic_node; |
| } |
| |
| /* string conversions */ |
| char *MULTI_PORT_MUX_string = "MULTI_PORT_MUX"; |
| char *FF_NODE_string = "FF_NODE"; |
| char *BUF_NODE_string = "BUF_NODE"; |
| char *INPUT_NODE_string = "INPUT_NODE"; |
| char *CLOCK_NODE_string = "CLOCK_NODE"; |
| char *OUTPUT_NODE_string = "OUTPUT_NODE"; |
| char *GND_NODE_string = "GND_NODE"; |
| char *VCC_NODE_string = "VCC_NODE"; |
| char *ADD_string = "ADD"; |
| char *MINUS_string = "MINUS"; |
| char *BITWISE_NOT_string = "BITWISE_NOT"; |
| char *BITWISE_AND_string = "BITWISE_AND"; |
| char *BITWISE_OR_string = "BITWISE_OR"; |
| char *BITWISE_NAND_string = "BITWISE_NAND"; |
| char *BITWISE_NOR_string = "BITWISE_NOR"; |
| char *BITWISE_XNOR_string = "BITWISE_XNOR"; |
| char *BITWISE_XOR_string = "BITWISE_XOR"; |
| char *LOGICAL_NOT_string = "LOGICAL_NOT"; |
| char *LOGICAL_OR_string = "LOGICAL_OR"; |
| char *LOGICAL_AND_string = "LOGICAL_AND"; |
| char *LOGICAL_NAND_string = "LOGICAL_NAND"; |
| char *LOGICAL_NOR_string = "LOGICAL_NOR"; |
| char *LOGICAL_XOR_string = "LOGICAL_XOR"; |
| char *LOGICAL_XNOR_string = "LOGICAL_XNOR"; |
| char *MULTIPLY_string = "MULTIPLY"; |
| char *DIVIDE_string = "DIVIDE"; |
| char *MODULO_string = "MODULO"; |
| char *LT_string = "LT"; |
| char *GT_string = "GT"; |
| char *LOGICAL_EQUAL_string = "LOGICAL_EQUAL"; |
| char *NOT_EQUAL_string = "NOT_EQUAL"; |
| char *LTE_string = "LTE"; |
| char *GTE_string = "GTE"; |
| char *SR_string = "SR"; |
| char *SL_string = "SL"; |
| char *CASE_EQUAL_string = "CASE_EQUAL"; |
| char *CASE_NOT_EQUAL_string = "CASE_NOT_EQUAL"; |
| char *ADDER_FUNC_string = "ADDER_FUNC"; |
| char *CARRY_FUNC_string = "CARRY_FUNC"; |
| char *MUX_2_string = "MUX_2"; |
| char *HARD_IP_string = "HARD_IP"; |
| char *MEMORY_string = "MEMORY"; |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: node_name_based_on_op) |
| * Get the string version of a node |
| *-------------------------------------------------------------------------------------------*/ |
| char *node_name_based_on_op(nnode_t *node) |
| { |
| char *return_string; |
| |
| switch(node->type) |
| { |
| case MULTI_PORT_MUX: |
| return_string = MULTI_PORT_MUX_string; |
| break; |
| case FF_NODE: |
| return_string = FF_NODE_string; |
| break; |
| case BUF_NODE: |
| return_string = BUF_NODE_string; |
| break; |
| case CLOCK_NODE: |
| return_string = CLOCK_NODE_string; |
| break; |
| case INPUT_NODE: |
| return_string = INPUT_NODE_string; |
| break; |
| case OUTPUT_NODE: |
| return_string = OUTPUT_NODE_string; |
| break; |
| case GND_NODE: |
| return_string = GND_NODE_string; |
| break; |
| case VCC_NODE: |
| return_string = VCC_NODE_string; |
| break; |
| case ADD: |
| return_string = ADD_string; |
| break; |
| case MINUS: |
| return_string = MINUS_string; |
| break; |
| case BITWISE_NOT: |
| return_string = BITWISE_NOT_string; |
| break; |
| case BITWISE_AND: |
| return_string = BITWISE_AND_string; |
| break; |
| case BITWISE_OR: |
| return_string = BITWISE_OR_string; |
| break; |
| case BITWISE_NAND: |
| return_string = BITWISE_NAND_string; |
| break; |
| case BITWISE_NOR: |
| return_string = BITWISE_NOR_string; |
| break; |
| case BITWISE_XNOR: |
| return_string = BITWISE_XNOR_string; |
| break; |
| case BITWISE_XOR: |
| return_string = BITWISE_XOR_string; |
| break; |
| case LOGICAL_NOT: |
| return_string = LOGICAL_NOT_string; |
| break; |
| case LOGICAL_OR: |
| return_string = LOGICAL_OR_string; |
| break; |
| case LOGICAL_AND: |
| return_string = LOGICAL_AND_string; |
| break; |
| case LOGICAL_NOR: |
| return_string = LOGICAL_NOR_string; |
| break; |
| case LOGICAL_NAND: |
| return_string = LOGICAL_NAND_string; |
| break; |
| case LOGICAL_XOR: |
| return_string = LOGICAL_XOR_string; |
| break; |
| case LOGICAL_XNOR: |
| return_string = LOGICAL_XNOR_string; |
| break; |
| case MULTIPLY: |
| return_string = MULTIPLY_string; |
| break; |
| case DIVIDE: |
| return_string = DIVIDE_string; |
| break; |
| case MODULO: |
| return_string = MODULO_string; |
| break; |
| case LT: |
| return_string = LT_string; |
| break; |
| case GT: |
| return_string = GT_string; |
| break; |
| case LOGICAL_EQUAL: |
| return_string = LOGICAL_EQUAL_string; |
| break; |
| case NOT_EQUAL: |
| return_string = NOT_EQUAL_string; |
| break; |
| case LTE: |
| return_string = LTE_string; |
| break; |
| case GTE: |
| return_string = GTE_string; |
| break; |
| case SR: |
| return_string = SR_string; |
| break; |
| case SL: |
| return_string = SL_string; |
| break; |
| case CASE_EQUAL: |
| return_string = CASE_EQUAL_string; |
| break; |
| case CASE_NOT_EQUAL: |
| return_string = CASE_NOT_EQUAL_string; |
| break; |
| case ADDER_FUNC: |
| return_string = ADDER_FUNC_string; |
| break; |
| case CARRY_FUNC: |
| return_string = CARRY_FUNC_string; |
| break; |
| case MUX_2: |
| return_string = MUX_2_string; |
| break; |
| case MEMORY: |
| return_string = MEMORY_string; |
| break; |
| case HARD_IP: |
| return_string = HARD_IP_string; |
| break; |
| default: |
| return_string = NULL; |
| oassert(FALSE); |
| break; |
| } |
| return return_string; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * (function: hard_node_name) |
| * This creates the unique node name for a hard block |
| *--------------------------------------------------------------------------*/ |
| char *hard_node_name(nnode_t *node, char *instance_name_prefix, char *hb_name, char *hb_inst) |
| { |
| char *return_node_name; |
| |
| /* create the unique name for this node */ |
| return_node_name = make_full_ref_name(instance_name_prefix, hb_name, hb_inst, NULL, -1); |
| |
| unique_node_name_id ++; |
| |
| return return_node_name; |
| } |
| |
| /*--------------------------------------------------------------------------------------------- |
| * (function: node_name) |
| * This creates the unique node name |
| *-------------------------------------------------------------------------------------------*/ |
| char *node_name(nnode_t *node, char *instance_name_prefix) |
| { |
| char *return_node_name; |
| |
| /* create the unique name for this node */ |
| return_node_name = make_full_ref_name(instance_name_prefix, NULL, NULL, node_name_based_on_op(node), unique_node_name_id); |
| |
| //oassert(unique_node_name_id != 199803); |
| |
| unique_node_name_id++; |
| |
| return return_node_name; |
| } |
| |
| /*------------------------------------------------------------------------- |
| * (function: make_mult_block) |
| * Just make a multiplier hard block |
| *-----------------------------------------------------------------------*/ |
| nnode_t *make_mult_block(nnode_t *node, short mark) |
| { |
| nnode_t *logic_node; |
| |
| logic_node = allocate_nnode(); |
| logic_node->traverse_visited = mark; |
| logic_node->type = MULTIPLY; |
| logic_node->name = node_name(logic_node, node->name); |
| logic_node->related_ast_node = node->related_ast_node; |
| logic_node->input_port_sizes = node->input_port_sizes; |
| logic_node->num_input_port_sizes = node->num_input_port_sizes; |
| logic_node->output_port_sizes = node->output_port_sizes; |
| logic_node->num_output_port_sizes = node->num_output_port_sizes; |
| |
| allocate_more_node_input_pins(logic_node, node->num_input_pins); |
| allocate_more_node_output_pins(logic_node, node->num_output_pins); |
| |
| return logic_node; |
| } |
| |