blob: bcb3cf7c940480203ef2892b244d35723745a731 [file] [log] [blame]
/*
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 "odin_types.h"
#include "odin_globals.h"
#include "netlist_utils.h"
#include "odin_util.h"
#include "node_creation_library.h"
#include "vtr_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_pad_pin(netlist_t *netlist)
{
npin_t *pad_fanout_pin = allocate_npin();
pad_fanout_pin->name = vtr::strdup(pad_string);
add_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_zero_pin(netlist_t *netlist)
{
npin_t *zero_fanout_pin = allocate_npin();
zero_fanout_pin->name = vtr::strdup(zero_string);
add_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_one_pin(netlist_t *netlist)
{
npin_t *one_fanout_pin = allocate_npin();
one_fanout_pin->name = vtr::strdup(one_string);
add_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_input_pin_to_node(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_input_pins(logic_node, 1);
allocate_more_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_input_pins(logic_node, width_input);
add_input_port_information(logic_node, width_input);
/* add output */
allocate_more_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 = 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_input_pin_to_node(logic_node, pin_list->pins[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_input_pins(logic_node, width_port1);
add_input_port_information(logic_node, width_port1);
allocate_more_input_pins(logic_node, width_port2);
add_input_port_information(logic_node, width_port2);
allocate_more_input_pins(logic_node, width_port3);
add_input_port_information(logic_node, width_port3);
/* add output */
allocate_more_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_input_pins(logic_node, width_port1);
add_input_port_information(logic_node, width_port1);
allocate_more_input_pins(logic_node, width_port2);
add_input_port_information(logic_node, width_port2);
/* add output */
allocate_more_output_pins(logic_node, width_output);
add_output_port_information(logic_node, width_output);
return logic_node;
}
/*---------------------------------------------------------------------------------------------
* (function: make_nport_logic_gates)
* Make a n port gate with variable sizes. The first port will be input_pins index 0..width_port1.
*-------------------------------------------------------------------------------------------*/
nnode_t *make_nport_gate(operation_list type, int port_sizes, int width, int width_output, nnode_t *node, short mark)
{
int i;
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 */
for(i = 0; i < port_sizes; i++) {
allocate_more_input_pins(logic_node, width);
add_input_port_information(logic_node, width);
}
//allocate_more_input_pins(logic_node, width_port2);
//add_input_port_information(logic_node, width_port2);
/* add output */
allocate_more_output_pins(logic_node, width_output);
add_output_port_information(logic_node, width_output);
return logic_node;
}
const char *edge_type_blif_str(nnode_t *node)
{
if(node->type != FF_NODE)
return NULL;
switch(node->edge_type)
{
case FALLING_EDGE_SENSITIVITY: return "fe";
case RISING_EDGE_SENSITIVITY: return "re";
case ACTIVE_HIGH_SENSITIVITY: return "ah";
case ACTIVE_LOW_SENSITIVITY: return "al";
case ASYNCHRONOUS_SENSITIVITY: return "as";
default:
error_message(NETLIST_ERROR, node->line_number, node->file_number,
"undefined sensitivity kind for flip flop %s", edge_type_e_STR[node->edge_type]);
return NULL;
}
}
edge_type_e edge_type_blif_enum(std::string edge_kind_str)
{
if (edge_kind_str == "fe") return FALLING_EDGE_SENSITIVITY;
else if (edge_kind_str == "re") return RISING_EDGE_SENSITIVITY;
else if (edge_kind_str == "ah") return ACTIVE_HIGH_SENSITIVITY;
else if (edge_kind_str == "al") return ACTIVE_LOW_SENSITIVITY;
else if (edge_kind_str == "as") return ASYNCHRONOUS_SENSITIVITY;
else
{
error_message(NETLIST_ERROR, -1, -1,
"undefined sensitivity kind for flip flop %s", edge_kind_str.c_str());
return UNDEFINED_SENSITIVITY;
}
}
/*----------------------------------------------------------------------------
* (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_input_pins(logic_node, node->num_input_pins);
allocate_more_output_pins(logic_node, node->num_output_pins);
return logic_node;
}