/*---------------------------------------------------------------------------------------------
 * (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;

}
Esempio n. 2
0
/*---------------------------------------------------------------------------------------------
 * (function: instantiate_not_logic )
 *-------------------------------------------------------------------------------------------*/
void instantiate_not_logic(nnode_t *node, short mark, netlist_t *netlist)
{
	int width = node->num_input_pins;
	nnode_t **new_not_cells;
	int i;

	new_not_cells = (nnode_t**)malloc(sizeof(nnode_t*)*width);

	for (i = 0; i < width; i++)
	{
		new_not_cells[i] = make_not_gate(node, mark);
	}

	/* connect inputs and outputs */
	for(i = 0; i < width; i++)
	{
		/* Joining the inputs to the new soft NOT GATES */
		remap_pin_to_new_node(node->input_pins[i], new_not_cells[i], 0);
		remap_pin_to_new_node(node->output_pins[i], new_not_cells[i], 0);
	}

	free(new_not_cells);
}
Esempio n. 3
0
/*---------------------------------------------------------------------------------------------
 * (function:  instantiate_unary_sub )
 *	Does 2's complement which is the equivalent of a unary subtraction as a HW implementation.	
 *-------------------------------------------------------------------------------------------*/
void instantiate_unary_sub(nnode_t *node, short mark, netlist_t *netlist)
{
	int width;
	int i;
	nnode_t **new_add_cells;
	nnode_t **new_carry_cells;
	nnode_t **new_not_cells;

	oassert(node->num_input_pins > 0);
	oassert(node->num_input_port_sizes == 1);
	width = node->output_port_sizes[0];

	new_add_cells = (nnode_t**)malloc(sizeof(nnode_t*)*width);
	new_carry_cells = (nnode_t**)malloc(sizeof(nnode_t*)*width);
	new_not_cells = (nnode_t**)malloc(sizeof(nnode_t*)*width);

	/* create the adder units and the zero unit */
	for (i = 0; i < width; i++)
	{
		new_add_cells[i] = make_3port_gate(ADDER_FUNC, 1, 1, 1, 1, node, mark);
		new_not_cells[i] = make_not_gate(node, mark);
		if (i < width - 1)
		{
			new_carry_cells[i] = make_3port_gate(CARRY_FUNC, 1, 1, 1, 1, node, mark);
		}
	}

    	/* ground first carry in .  Note the one constant is inputted to start 2's complement */
	add_a_input_pin_to_node_spot_idx(new_add_cells[0], get_a_one_pin(netlist), 0);
	if (i > 1)
	{
		add_a_input_pin_to_node_spot_idx(new_carry_cells[0], get_a_one_pin(netlist), 0);
	}

	/* connect inputs */
	for(i = 0; i < width; i++)
	{
		/* join the A port up to adder */
		remap_pin_to_new_node(node->input_pins[i], new_not_cells[i], 0);
		connect_nodes(new_not_cells[i], 0, new_add_cells[i], 1);
		if (i < width - 1)
			connect_nodes(new_not_cells[i], 0, new_carry_cells[i], 1);

		add_a_input_pin_to_node_spot_idx(new_add_cells[i], get_a_zero_pin(netlist), 2);
		if (i < width - 1)
			add_a_input_pin_to_node_spot_idx(new_carry_cells[i], get_a_zero_pin(netlist), 2);

		/* join that gate to the output */
		remap_pin_to_new_node(node->output_pins[i], new_add_cells[i], 0);
	}
	
	/* connect carry outs with carry ins */
	for(i = 1; i < width; i++)
	{
		connect_nodes(new_carry_cells[i-1], 0, new_add_cells[i], 0);
		if (i < width - 1)
			connect_nodes(new_carry_cells[i-1], 0, new_carry_cells[i], 0);
	}

	free(new_add_cells);
	free(new_carry_cells);
}
Esempio n. 4
0
/*-------------------------------------------------------------------------
 * (function: split_dp_memory_depth)
 *
 * This function works to split the depth of a dual port memory into 
 *   several smaller memories.
 *------------------------------------------------------------------------
 */
void 
split_dp_memory_depth(nnode_t *node)
{
	int addr1_port = -1;
	int addr2_port = -1;
	int we1_port = -1;
	int we2_port = -1;
	int logical_size;
	int i, j;
	int idx;
	int addr1_pin_idx = 0;
	int we1_pin_idx = 0;
	int addr2_pin_idx = 0;
	int we2_pin_idx = 0;
	nnode_t *new_mem_node;
	nnode_t *and1_node, *not1_node, *ff1_node, *mux1_node;
	nnode_t *and2_node, *not2_node, *ff2_node, *mux2_node;
	npin_t *addr1_pin = NULL;
	npin_t *addr2_pin = NULL;
	npin_t *we1_pin = NULL;
	npin_t *we2_pin = NULL;
	npin_t *twe_pin, *taddr_pin;
	npin_t *clk_pin = NULL;
	npin_t *tdout_pin;

	oassert(node->type == MEMORY);

	/* Find which ports are the addr1 and addr2 ports */
	idx = 0;
	for (i = 0; i < node->num_input_port_sizes; i++)
	{
		if (strcmp("addr1", node->input_pins[idx]->mapping) == 0)
		{
			addr1_port = i;
			addr1_pin_idx = idx;
			addr1_pin = node->input_pins[idx];
		}
		else if (strcmp("addr2", node->input_pins[idx]->mapping) == 0)
		{
			addr2_port = i;
			addr2_pin_idx = idx;
			addr2_pin = node->input_pins[idx];
		}
		else if (strcmp("we1", node->input_pins[idx]->mapping) == 0)
		{
			we1_port = i;
			we1_pin = node->input_pins[idx];
			we1_pin_idx = idx;
		}
		else if (strcmp("we2", node->input_pins[idx]->mapping) == 0)
		{
			we2_port = i;
			we2_pin = node->input_pins[idx];
			we2_pin_idx = idx;
		}
		else if (strcmp("clk", node->input_pins[idx]->mapping) == 0)
		{
			clk_pin = node->input_pins[idx];
		}
		idx += node->input_port_sizes[i];
	}

	if (addr1_port == -1)
	{
		error_message(1, 0, -1, "No \"addr1\" port on dual port RAM");
	}

	
	/* Jason Luu HACK: Logical memory depth determination messed up, forced to use this method */
	for(i = 0; i < node->input_port_sizes[addr1_port]; i++)
	{
		if(strcmp(node->input_pins[addr1_pin_idx + i]->name, "top^ZERO_PAD_ZERO") == 0)
			break;
	}
	logical_size = i;
 	
	/* Check that the memory needs to be split */
	if (logical_size <= split_size) {
		dp_memory_list = insert_in_vptr_list(dp_memory_list, node);
		return;
	} 

	/* Let's remove the address1 line from the memory */
	for (i = addr1_pin_idx; i < node->num_input_pins - 1; i++)
	{
		node->input_pins[i] = node->input_pins[i+1];
		node->input_pins[i]->pin_node_idx--;
	}
	node->input_port_sizes[addr1_port]--;
	node->input_pins = realloc(node->input_pins, sizeof(npin_t *) * --node->num_input_pins);
	if ((we1_port != -1) && (we1_pin_idx >= addr1_pin_idx))
		we1_pin_idx--;
	if ((we2_port != -1) && (we2_pin_idx >= addr1_pin_idx))
		we2_pin_idx--;
	if ((addr2_port != -1) && (addr2_pin_idx >= addr1_pin_idx))
		addr2_pin_idx--;

	/* Let's remove the address2 line from the memory */
	if (addr2_port != -1)
	{
		for (i = addr2_pin_idx; i < node->num_input_pins - 1; i++)
		{
			node->input_pins[i] = node->input_pins[i+1];
			node->input_pins[i]->pin_node_idx--;
		}
		node->input_port_sizes[addr2_port]--;
		node->input_pins = realloc(node->input_pins, sizeof(npin_t *) * --node->num_input_pins);
		if ((we1_port != -1) && (we1_pin_idx >= addr2_pin_idx))
			we1_pin_idx--;
		if ((we2_port != -1) && (we2_pin_idx >= addr2_pin_idx))
			we2_pin_idx--;
		if (addr1_pin_idx >= addr2_pin_idx)
			addr1_pin_idx--;
	}

	/* Create the new memory node */
	new_mem_node = allocate_nnode();

	// Append the new name with an __H
	new_mem_node->name = append_string(node->name, "__H");

	{	// Append the old name with an __S
		char *new_name = append_string(node->name, "__S");
		free(node->name);
		node->name = new_name;
	}

	/* Copy properties from the original memory node */
	new_mem_node->type = node->type;
	new_mem_node->related_ast_node = node->related_ast_node;
	new_mem_node->traverse_visited = node->traverse_visited;

	// Copy over the port sizes for the new memory
	for (j = 0; j < node->num_output_port_sizes; j++)
		add_output_port_information(new_mem_node, node->output_port_sizes[j]);
	for (j = 0; j < node->num_input_port_sizes; j++)
		add_input_port_information (new_mem_node, node->input_port_sizes[j]);

	// allocate space for pins.
	allocate_more_node_output_pins (new_mem_node, node->num_output_pins);
	allocate_more_node_input_pins  (new_mem_node, node->num_input_pins);

	// Copy over the pins for the new memory
	for (j = 0; j < node->num_input_pins; j++)
		add_a_input_pin_to_node_spot_idx(new_mem_node, copy_input_npin(node->input_pins[j]), j);

	if (we1_pin != NULL)
	{
		and1_node = make_2port_gate(LOGICAL_AND, 1, 1, 1, node, node->traverse_visited);
		twe_pin = copy_input_npin(we1_pin);
		add_a_input_pin_to_node_spot_idx(and1_node, twe_pin, 1);
		taddr_pin = copy_input_npin(addr1_pin);
		add_a_input_pin_to_node_spot_idx(and1_node, taddr_pin, 0);
		connect_nodes(and1_node, 0, node, we1_pin_idx);
		node->input_pins[we1_pin_idx]->mapping = we1_pin->mapping;
	}

	if (we2_pin != NULL)
	{
		and2_node = make_2port_gate(LOGICAL_AND, 1, 1, 1, node, node->traverse_visited);
		twe_pin = copy_input_npin(we2_pin);
		add_a_input_pin_to_node_spot_idx(and2_node, twe_pin, 1);
		taddr_pin = copy_input_npin(addr2_pin);
		add_a_input_pin_to_node_spot_idx(and2_node, taddr_pin, 0);
		connect_nodes(and2_node, 0, node, we2_pin_idx);
		node->input_pins[we2_pin_idx]->mapping = we2_pin->mapping;
	}

	if (we1_pin != NULL)
	{
		taddr_pin = copy_input_npin(addr1_pin);
		not1_node = make_not_gate_with_input(taddr_pin, new_mem_node, new_mem_node->traverse_visited);
		and1_node = make_2port_gate(LOGICAL_AND, 1, 1, 1, new_mem_node, new_mem_node->traverse_visited);
		connect_nodes(not1_node, 0, and1_node, 0);
		add_a_input_pin_to_node_spot_idx(and1_node, we1_pin, 1);
		connect_nodes(and1_node, 0, new_mem_node, we1_pin_idx);
		new_mem_node->input_pins[we1_pin_idx]->mapping = we1_pin->mapping;
	}

	if (we2_pin != NULL)
	{
		taddr_pin = copy_input_npin(addr2_pin);
		not2_node = make_not_gate_with_input(taddr_pin, new_mem_node, new_mem_node->traverse_visited);
		and2_node = make_2port_gate(LOGICAL_AND, 1, 1, 1, new_mem_node, new_mem_node->traverse_visited);
		connect_nodes(not2_node, 0, and2_node, 0);
		add_a_input_pin_to_node_spot_idx(and2_node, we2_pin, 1);
		connect_nodes(and2_node, 0, new_mem_node, we2_pin_idx);
		new_mem_node->input_pins[we2_pin_idx]->mapping = we2_pin->mapping;
	}

	if (node->num_output_pins > 0) /* There is an "out1" output */
	{
		ff1_node = make_2port_gate(FF_NODE, 1, 1, 1, node, node->traverse_visited);
		add_a_input_pin_to_node_spot_idx(ff1_node, addr1_pin, 0);
		add_a_input_pin_to_node_spot_idx(ff1_node, copy_input_npin(clk_pin), 1);

		/* Copy over the output pins for the new memory */
		for (j = 0; j < node->output_port_sizes[0]; j++)
		{
			mux1_node = make_2port_gate(MUX_2, 2, 2, 1, node, node->traverse_visited);
			connect_nodes(ff1_node, 0, mux1_node, 0);
			not1_node = make_not_gate(node, node->traverse_visited);
			connect_nodes(ff1_node, 0, not1_node, 0);
			connect_nodes(not1_node, 0, mux1_node, 1);
			tdout_pin = node->output_pins[j];
			remap_pin_to_new_node(tdout_pin, mux1_node, 0);
			connect_nodes(node, j, mux1_node, 2);
			node->output_pins[j]->mapping = tdout_pin->mapping;
			connect_nodes(new_mem_node, j, mux1_node, 3);
			new_mem_node->output_pins[j]->mapping = tdout_pin->mapping;
			tdout_pin->mapping = NULL;

			mux1_node->output_pins[0]->name = mux1_node->name;
		}
	}

	if (node->num_output_pins > node->output_port_sizes[0]) /* There is an "out2" output */
	{
		ff2_node = make_2port_gate(FF_NODE, 1, 1, 1, node, node->traverse_visited);
		add_a_input_pin_to_node_spot_idx(ff2_node, addr2_pin, 0);
		add_a_input_pin_to_node_spot_idx(ff2_node, copy_input_npin(clk_pin), 1);

		/* Copy over the output pins for the new memory */
		for (j = 0; j < node->output_port_sizes[0]; j++)
		{
			mux2_node = make_2port_gate(MUX_2, 2, 2, 1, node, node->traverse_visited);
			connect_nodes(ff2_node, 0, mux2_node, 0);
			not2_node = make_not_gate(node, node->traverse_visited);

			connect_nodes(ff2_node, 0, not2_node, 0);
			connect_nodes(not2_node, 0, mux2_node, 1);

			tdout_pin = node->output_pins[node->output_port_sizes[0] + j];
			remap_pin_to_new_node(tdout_pin, mux2_node, 0);

			connect_nodes(node, node->output_port_sizes[0] + j, mux2_node, 2);
			node->output_pins[node->output_port_sizes[0] + j]->mapping = tdout_pin->mapping;
			connect_nodes(new_mem_node, node->output_port_sizes[0] + j, mux2_node, 3);
			new_mem_node->output_pins[node->output_port_sizes[0] + j]->mapping = tdout_pin->mapping;
			tdout_pin->mapping = NULL;

			mux2_node->output_pins[0]->name = mux2_node->name;
		}
	}

	/* must recurse on new memory if it's too small */
	if (logical_size <= split_size) {
		dp_memory_list = insert_in_vptr_list(dp_memory_list, new_mem_node);
		dp_memory_list = insert_in_vptr_list(dp_memory_list, node);
	} else {
		split_dp_memory_depth(node);
		split_dp_memory_depth(new_mem_node);
	}

	return;
}
Esempio n. 5
0
/*-------------------------------------------------------------------------
 * (function: split_sp_memory_depth)
 *
 * This function works to split the depth of a single port memory into 
 *   several smaller memories.
 *------------------------------------------------------------------------
 */
void
split_sp_memory_depth(nnode_t *node)
{
	int data_port = -1;
	int clk_port  = -1;
	int addr_port = -1;
	int we_port = -1;
	int logical_size;
	int i, j;
	int idx;
	int addr_pin_idx = 0;
	int we_pin_idx = 0;
	nnode_t *new_mem_node;
	nnode_t *and_node, *not_node,  *mux_node, *ff_node;
	npin_t *addr_pin = NULL;
	npin_t *we_pin = NULL;
	npin_t *clk_pin = NULL;
	npin_t *tdout_pin;


	oassert(node->type == MEMORY);


	// Find which port is the addr port
	idx = 0;
	for (i = 0; i < node->num_input_port_sizes; i++)
	{
		//printf("%s\n", node->input_pins[idx]->mapping);
		if (strcmp("addr", node->input_pins[idx]->mapping) == 0)
		{
			addr_port = i;
			addr_pin_idx = idx;
			addr_pin = node->input_pins[idx];
		}
		else if (strcmp("data", node->input_pins[idx]->mapping) == 0)
		{
			data_port = i;
		}
		else if (strcmp("we", node->input_pins[idx]->mapping) == 0)
		{
			we_port = i;
			we_pin = node->input_pins[idx];
			we_pin_idx = idx;
		}
		else if (strcmp("clk", node->input_pins[idx]->mapping) == 0)
		{
			clk_port = i;
			clk_pin = node->input_pins[idx];
		}
		idx += node->input_port_sizes[i];
	}
	if (data_port == -1)
	{
		error_message(1, 0, -1, "No \"data\" port on single port RAM");
	}
	if (addr_port == -1)
	{
		error_message(1, 0, -1, "No \"addr\" port on single port RAM");
	}
	if (we_port == -1)
	{
		error_message(1, 0, -1, "No \"we\" port on single port RAM");
	}
	if (clk_port == -1)
	{
		error_message(1, 0, -1, "No \"clk\" port on single port RAM");
	}
	
	// Check that the memory needs to be split
	// Jason Luu HACK: Logical memory depth determination messed up, forced to use this method
	for(i = 0; i < node->input_port_sizes[addr_port]; i++)
	{
		if(strcmp(node->input_pins[addr_pin_idx + i]->name, "top^ZERO_PAD_ZERO") == 0)
			break;
	}
	logical_size = i;
	if (split_size <= 0)
	{
		printf("Unsupported feature! Split size must be a positive number\n");
		exit(1);
	}
	if ((split_size > 0) && (logical_size <= split_size)) {
		sp_memory_list = insert_in_vptr_list(sp_memory_list, node);
		return;
	}

	// Let's remove the address line from the memory
	for (i = addr_pin_idx; i < node->num_input_pins - 1; i++)
	{
		node->input_pins[i] = node->input_pins[i+1];
		node->input_pins[i]->pin_node_idx--;
	}
	node->input_port_sizes[addr_port]--;
	node->input_pins = realloc(node->input_pins, sizeof(npin_t *) * --node->num_input_pins);

	if (we_pin_idx >= addr_pin_idx)
		we_pin_idx--;

	// Create the new memory node
	new_mem_node = allocate_nnode();
	// Append the new name with an __H
	new_mem_node->name = append_string(node->name, "__H");

	{	// Append the old name with an __S
		char *new_name = append_string(node->name, "__S");
		free(node->name);
		node->name = new_name;
	}

	// Copy properties from the original memory node
	new_mem_node->type = node->type;
	new_mem_node->related_ast_node = node->related_ast_node;
	new_mem_node->traverse_visited = node->traverse_visited;

	add_output_port_information(new_mem_node, node->num_output_pins);
	allocate_more_node_output_pins (new_mem_node, node->num_output_pins);

	for (j = 0; j < node->num_input_port_sizes; j++)
		add_input_port_information(new_mem_node, node->input_port_sizes[j]);

	// Copy over the input pins for the new memory, excluding we
	allocate_more_node_input_pins (new_mem_node, node->num_input_pins);
	for (j = 0; j < node->num_input_pins; j++)
	{
		if (j != we_pin_idx)
			add_a_input_pin_to_node_spot_idx(new_mem_node, copy_input_npin(node->input_pins[j]), j);
	}

	and_node = make_2port_gate(LOGICAL_AND, 1, 1, 1, node, node->traverse_visited);
	add_a_input_pin_to_node_spot_idx(and_node, we_pin, 1);
	add_a_input_pin_to_node_spot_idx(and_node, addr_pin, 0);
	connect_nodes(and_node, 0, node, we_pin_idx);
	node->input_pins[we_pin_idx]->mapping = we_pin->mapping;

	not_node = make_not_gate_with_input(copy_input_npin(addr_pin), new_mem_node, new_mem_node->traverse_visited);
	and_node = make_2port_gate(LOGICAL_AND, 1, 1, 1, new_mem_node, new_mem_node->traverse_visited);
	connect_nodes(not_node, 0, and_node, 0);
	add_a_input_pin_to_node_spot_idx(and_node, copy_input_npin(we_pin), 1);
	connect_nodes(and_node, 0, new_mem_node, we_pin_idx);
	new_mem_node->input_pins[we_pin_idx]->mapping = we_pin->mapping;

	ff_node = make_2port_gate(FF_NODE, 1, 1, 1, node, node->traverse_visited);
	add_a_input_pin_to_node_spot_idx(ff_node, copy_input_npin(addr_pin), 0);
	add_a_input_pin_to_node_spot_idx(ff_node, copy_input_npin(clk_pin), 1);

	// Copy over the output pins for the new memory
	for (j = 0; j < node->num_output_pins; j++)
	{
		mux_node = make_2port_gate(MUX_2, 2, 2, 1, node, node->traverse_visited);
		connect_nodes(ff_node, 0, mux_node, 0);

		not_node = make_not_gate(node, node->traverse_visited);
		connect_nodes(ff_node, 0, not_node, 0);
		connect_nodes(not_node, 0, mux_node, 1);

		tdout_pin = node->output_pins[j];
		remap_pin_to_new_node(tdout_pin, mux_node, 0);

		connect_nodes(node, j, mux_node, 2);
		node->output_pins[j]->mapping = tdout_pin->mapping;

		connect_nodes(new_mem_node, j, mux_node, 3);
		new_mem_node->output_pins[j]->mapping = tdout_pin->mapping;

		tdout_pin->mapping = NULL;

		mux_node->output_pins[0]->name = mux_node->name;
	}

	// must recurse on new memory if it's too small
	if (logical_size <= split_size) {
		sp_memory_list = insert_in_vptr_list(sp_memory_list, new_mem_node);
		sp_memory_list = insert_in_vptr_list(sp_memory_list, node);
	} else {
		split_sp_memory_depth(node);
		split_sp_memory_depth(new_mem_node);
	}

	return;
}