<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  <NAME> <<EMAIL>>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

SigMap assign_map, dff_init_map;
SigSet<RTLIL::Cell*> mux_drivers;
dict<SigBit, pool<SigBit>> init_attributes;
bool keepdc;

void remove_init_attr(SigSpec sig)
{
	for (auto bit : assign_map(sig))
		if (init_attributes.count(bit))
			for (auto wbit : init_attributes.at(bit))
				wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx;
}

bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
{
	SigSpec sig_set, sig_clr;
	State pol_set, pol_clr;

	if (cell->hasPort("\\S"))
		sig_set = cell->getPort("\\S");

	if (cell->hasPort("\\R"))
		sig_clr = cell->getPort("\\R");

	if (cell->hasPort("\\SET"))
		sig_set = cell->getPort("\\SET");

	if (cell->hasPort("\\CLR"))
		sig_clr = cell->getPort("\\CLR");

	log_assert(GetSize(sig_set) == GetSize(sig_clr));

	if (cell->type.substr(0,8) == "$_DFFSR_") {
		pol_set = cell->type[9] == 'P' ? State::S1 : State::S0;
		pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0;
	} else
	if (cell->type.substr(0,11) == "$_DLATCHSR_") {
		pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
		pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
	} else
	if (cell->type == "$dffsr" || cell->type == "$dlatchsr") {
		pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0;
		pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0;
	} else
		log_abort();

	State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
	State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;

	SigSpec sig_d = cell->getPort("\\D");
	SigSpec sig_q = cell->getPort("\\Q");

	bool did_something = false;
	bool proper_sr = false;
	bool used_pol_set = false;
	bool used_pol_clr = false;
	bool hasreset = false;
	Const reset_val;
	SigSpec sig_reset;

	for (int i = 0; i < GetSize(sig_set); i++)
	{
		SigBit s = sig_set[i], c = sig_clr[i];

		if (s != npol_set || c != npol_clr)
			hasreset = true;

		if (s == pol_set || c == pol_clr)
		{
			log("Constantly %s Q bit %s for SR cell %s (%s) from module %s.\n",
					s == pol_set ? "set" : "cleared", log_signal(sig_q[i]),
					log_id(cell), log_id(cell->type), log_id(mod));

			remove_init_attr(sig_q[i]);
			mod->connect(sig_q[i], s == pol_set ? State::S1 : State::S0);
			sig_set.remove(i);
			sig_clr.remove(i);
			sig_d.remove(i);
			sig_q.remove(i--);
			did_something = true;
			continue;
		}
		if (sig_reset.empty() && s.wire != nullptr) sig_reset = s;
		if (sig_reset.empty() && c.wire != nullptr) sig_reset = c;

		if (s.wire != nullptr && s != sig_reset) proper_sr = true;
		if (c.wire != nullptr && c != sig_reset) proper_sr = true;

		if ((s.wire == nullptr) != (c.wire == nullptr)) {
			if (s.wire != nullptr) used_pol_set = true;
			if (c.wire != nullptr) used_pol_clr = true;
			reset_val.bits.push_back(c.wire == nullptr ? State::S1 : State::S0);
		} else
			proper_sr = true;
	}

	if (!hasreset)
		proper_sr = false;

	if (GetSize(sig_set) == 0)
	{
		log("Removing %s (%s) from module %s.\n", log_id(cell), log_id(cell->type), log_id(mod));
		mod->remove(cell);
		return true;
	}

	if (cell->type == "$dffsr" || cell->type == "$dlatchsr")
	{
		cell->setParam("\\WIDTH", GetSize(sig_d));
		cell->setPort("\\SET", sig_set);
		cell->setPort("\\CLR", sig_clr);
		cell->setPort("\\D", sig_d);
		cell->setPort("\\Q", sig_q);
	}
	else
	{
		cell->setPort("\\S", sig_set);
		cell->setPort("\\R", sig_clr);
		cell->setPort("\\D", sig_d);
		cell->setPort("\\Q", sig_q);
	}

	if (proper_sr)
		return did_something;

	if (used_pol_set && used_pol_clr && pol_set != pol_clr)
		return did_something;

	State unified_pol = used_pol_set ? pol_set : pol_clr;

	if (cell->type == "$dffsr")
	{
		if (hasreset)
		{
			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));

			cell->type = "$adff";
			cell->setParam("\\ARST_POLARITY", unified_pol);
			cell->setParam("\\ARST_VALUE", reset_val);
			cell->setPort("\\ARST", sig_reset);

			cell->unsetParam("\\SET_POLARITY");<commit_msg>Fix opt_rmdff handling of $dlatchsr<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  <NAME> <<EMAIL>>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

SigMap assign_map, dff_init_map;
SigSet<RTLIL::Cell*> mux_drivers;
dict<SigBit, pool<SigBit>> init_attributes;
bool keepdc;

void remove_init_attr(SigSpec sig)
{
	for (auto bit : assign_map(sig))
		if (init_attributes.count(bit))
			for (auto wbit : init_attributes.at(bit))
				wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx;
}

bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
{
	SigSpec sig_set, sig_clr;
	State pol_set, pol_clr;

	if (cell->hasPort("\\S"))
		sig_set = cell->getPort("\\S");

	if (cell->hasPort("\\R"))
		sig_clr = cell->getPort("\\R");

	if (cell->hasPort("\\SET"))
		sig_set = cell->getPort("\\SET");

	if (cell->hasPort("\\CLR"))
		sig_clr = cell->getPort("\\CLR");

	log_assert(GetSize(sig_set) == GetSize(sig_clr));

	if (cell->type.substr(0,8) == "$_DFFSR_") {
		pol_set = cell->type[9] == 'P' ? State::S1 : State::S0;
		pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0;
	} else
	if (cell->type.substr(0,11) == "$_DLATCHSR_") {
		pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
		pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
	} else
	if (cell->type == "$dffsr" || cell->type == "$dlatchsr") {
		pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0;
		pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0;
	} else
		log_abort();

	State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
	State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;

	SigSpec sig_d = cell->getPort("\\D");
	SigSpec sig_q = cell->getPort("\\Q");

	bool did_something = false;
	bool proper_sr = false;
	bool used_pol_set = false;
	bool used_pol_clr = false;
	bool hasreset = false;
	Const reset_val;
	SigSpec sig_reset;

	for (int i = 0; i < GetSize(sig_set); i++)
	{
		SigBit s = sig_set[i], c = sig_clr[i];

		if (s != npol_set || c != npol_clr)
			hasreset = true;

		if (s == pol_set || c == pol_clr)
		{
			log("Constantly %s Q bit %s for SR cell %s (%s) from module %s.\n",
					s == pol_set ? "set" : "cleared", log_signal(sig_q[i]),
					log_id(cell), log_id(cell->type), log_id(mod));

			remove_init_attr(sig_q[i]);
			mod->connect(sig_q[i], s == pol_set ? State::S1 : State::S0);
			sig_set.remove(i);
			sig_clr.remove(i);
			sig_d.remove(i);
			sig_q.remove(i--);
			did_something = true;
			continue;
		}
		if (sig_reset.empty() && s.wire != nullptr) sig_reset = s;
		if (sig_reset.empty() && c.wire != nullptr) sig_reset = c;

		if (s.wire != nullptr && s != sig_reset) proper_sr = true;
		if (c.wire != nullptr && c != sig_reset) proper_sr = true;

		if ((s.wire == nullptr) != (c.wire == nullptr)) {
			if (s.wire != nullptr) used_pol_set = true;
			if (c.wire != nullptr) used_pol_clr = true;
			reset_val.bits.push_back(c.wire == nullptr ? State::S1 : State::S0);
		} else
			proper_sr = true;
	}

	if (!hasreset)
		proper_sr = false;

	if (GetSize(sig_set) == 0)
	{
		log("Removing %s (%s) from module %s.\n", log_id(cell), log_id(cell->type), log_id(mod));
		mod->remove(cell);
		return true;
	}

	if (cell->type == "$dffsr" || cell->type == "$dlatchsr")
	{
		cell->setParam("\\WIDTH", GetSize(sig_d));
		cell->setPort("\\SET", sig_set);
		cell->setPort("\\CLR", sig_clr);
		cell->setPort("\\D", sig_d);
		cell->setPort("\\Q", sig_q);
	}
	else
	{
		cell->setPort("\\S", sig_set);
		cell->setPort("\\R", sig_clr);
		cell->setPort("\\D", sig_d);
		cell->setPort("\\Q", sig_q);
	}

	if (proper_sr)
		return did_something;

	if (used_pol_set && used_pol_clr && pol_set != pol_clr)
		return did_something;

	if (cell->type == "$dlatchsr")
		return did_something;

	State unified_pol = used_pol_set ? pol_set : pol_clr;

	if (cell->type == "$dffsr")
	{
		if (hasreset)
		{
			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));

			cell->type = "$adff";
			cell->setParam("\\ARST_POLARITY", unified_pol);
			cell->setParam("\\ARST_VALUE", reset_val);
			cell->setPort("\\ARST", sig_reset);

			cell->unsetParam("\\SET_POLARITY");
{'fraction_non_alphanumeric': 0.18226111166351794, 'fraction_numerical': 0.007954658446852938, 'mean_word_length': 3.944936086529007, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 106, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2723810', 'n_tokens_mistral': 4246, 'n_tokens_neox': 3935, 'n_words': 926}