mirror of https://github.com/YosysHQ/yosys.git
move wand/wor resolution into hierarchy pass
This commit is contained in:
parent
85de9d26c1
commit
ed625a3102
|
@ -163,42 +163,6 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
|
|||
return wire;
|
||||
}
|
||||
|
||||
// helper function for creating RTLIL code for wand/wor declarations
|
||||
static void wandwor2rtlil(AstNode *that, RTLIL::Wire *output_wire, bool gen_attributes = true)
|
||||
{
|
||||
std::string type;
|
||||
|
||||
if (that->is_wand) {
|
||||
type = "$reduce_and";
|
||||
} else if (that->is_wor) {
|
||||
type = "$reduce_or";
|
||||
} else {
|
||||
log_file_error(that->filename, that->linenum, "Unrecognized wired logic type.\n");
|
||||
}
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++);
|
||||
|
||||
RTLIL::Cell *cell = current_module->addCell(sstr.str(), type);
|
||||
cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
|
||||
|
||||
if (gen_attributes)
|
||||
for (auto &attr : that->attributes) {
|
||||
if (attr.second->type != AST_CONSTANT)
|
||||
log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
|
||||
cell->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
|
||||
cell->parameters["\\A_WIDTH"] = RTLIL::Const(0);
|
||||
cell->setPort("\\A", RTLIL::SigSpec());
|
||||
|
||||
cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
|
||||
cell->setPort("\\Y", output_wire);
|
||||
|
||||
wire_logic_map[output_wire] = cell;
|
||||
}
|
||||
|
||||
// helper class for converting AST always nodes to RTLIL processes
|
||||
struct AST_INTERNAL::ProcessGenerator
|
||||
{
|
||||
|
@ -956,11 +920,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
wire->attributes[attr.first] = attr.second->asAttrConst();
|
||||
}
|
||||
|
||||
if (is_wand || is_wor) {
|
||||
if (wire->width > 1)
|
||||
log_file_error(filename, linenum, "Multi-bit wand/wor not supported.\n");
|
||||
wandwor2rtlil(this, wire);
|
||||
}
|
||||
if (is_wand) wire->set_bool_attribute("\\wand");
|
||||
if (is_wor) wire->set_bool_attribute("\\wor");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1492,43 +1453,23 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
// add entries to current_module->connections for assignments (outside of always blocks)
|
||||
case AST_ASSIGN:
|
||||
{
|
||||
bool left_had_const = false;
|
||||
RTLIL::SigSpec left = children[0]->genRTLIL();
|
||||
RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size());
|
||||
|
||||
RTLIL::SigSpec new_left, new_right;
|
||||
for (int i = 0; i < GetSize(left); i++)
|
||||
if (left[i].wire) {
|
||||
std::map<RTLIL::SigSpec, RTLIL::Cell*>::iterator iter = wire_logic_map.find(left[i].wire);
|
||||
if (iter == wire_logic_map.end()) {
|
||||
if (left.has_const()) {
|
||||
RTLIL::SigSpec new_left, new_right;
|
||||
for (int i = 0; i < GetSize(left); i++)
|
||||
if (left[i].wire) {
|
||||
new_left.append(left[i]);
|
||||
} else {
|
||||
RTLIL::Cell *reduce_cell = iter->second;
|
||||
RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A");
|
||||
int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int();
|
||||
|
||||
RTLIL::Wire *new_reduce_input = current_module->addWire(
|
||||
stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width));
|
||||
new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
reduce_cell_in.append(new_reduce_input);
|
||||
reduce_cell->setPort("\\A", reduce_cell_in);
|
||||
reduce_cell->fixup_parameters();
|
||||
new_left.append(new_reduce_input);
|
||||
new_right.append(right[i]);
|
||||
}
|
||||
new_right.append(right[i]);
|
||||
} else {
|
||||
left_had_const = true;
|
||||
}
|
||||
|
||||
left = new_left;
|
||||
right = new_right;
|
||||
current_module->connect(RTLIL::SigSig(left, right));
|
||||
|
||||
if (left_had_const)
|
||||
log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
|
||||
" old assignment: %s = %s\n new assignment: %s = %s.\n",
|
||||
log_signal(left), log_signal(right),
|
||||
log_signal(new_left), log_signal(new_right));
|
||||
left = new_left;
|
||||
right = new_right;
|
||||
}
|
||||
current_module->connect(RTLIL::SigSig(left, right));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1573,38 +1514,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
}
|
||||
if (child->type == AST_ARGUMENT) {
|
||||
RTLIL::SigSpec sig;
|
||||
RTLIL::SigSpec new_sig;
|
||||
if (child->children.size() > 0) {
|
||||
if (child->children.size() > 0)
|
||||
sig = child->children[0]->genRTLIL();
|
||||
for (int i = 0; i < GetSize(sig); i++) {
|
||||
if (sig[i].wire) {
|
||||
std::map<RTLIL::SigSpec, RTLIL::Cell*>::iterator iter = wire_logic_map.find(sig[i].wire);
|
||||
if (iter == wire_logic_map.end()) {
|
||||
new_sig.append(sig[i]);
|
||||
} else {
|
||||
RTLIL::Cell *reduce_cell = iter->second;
|
||||
RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A");
|
||||
int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int();
|
||||
|
||||
RTLIL::Wire *new_reduce_input = current_module->addWire(
|
||||
stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width));
|
||||
new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||
reduce_cell_in.append(new_reduce_input);
|
||||
reduce_cell->setPort("\\A", reduce_cell_in);
|
||||
reduce_cell->fixup_parameters();
|
||||
new_sig.append(new_reduce_input);
|
||||
}
|
||||
} else {
|
||||
new_sig.append(sig[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (child->str.size() == 0) {
|
||||
char buf[100];
|
||||
snprintf(buf, 100, "$%d", ++port_counter);
|
||||
cell->setPort(buf, new_sig);
|
||||
cell->setPort(buf, sig);
|
||||
} else {
|
||||
cell->setPort(child->str, new_sig);
|
||||
cell->setPort(child->str, sig);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -562,7 +562,7 @@ struct HierarchyPass : public Pass {
|
|||
log("In parametric designs, a module might exists in several variations with\n");
|
||||
log("different parameter values. This pass looks at all modules in the current\n");
|
||||
log("design an re-runs the language frontends for the parametric modules as\n");
|
||||
log("needed.\n");
|
||||
log("needed. It also resolves assignments to wired logic data types (wand/wor).\n");
|
||||
log("\n");
|
||||
log(" -check\n");
|
||||
log(" also check the design hierarchy. this generates an error when\n");
|
||||
|
@ -941,6 +941,61 @@ struct HierarchyPass : public Pass {
|
|||
|
||||
std::set<Module*> blackbox_derivatives;
|
||||
std::vector<Module*> design_modules = design->modules();
|
||||
std::map<Wire*, Cell*> wlogic_map;
|
||||
|
||||
for (auto module : design_modules)
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
Cell *reduce = nullptr;
|
||||
if (wire->get_bool_attribute("\\wand")) {
|
||||
reduce = module->addCell(
|
||||
stringf("$%s_reduce", wire->name.c_str()), "$reduce_and");
|
||||
}
|
||||
if (wire->get_bool_attribute("\\wor")) {
|
||||
reduce = module->addCell(
|
||||
stringf("$%s_reduce", wire->name.c_str()), "$reduce_or");
|
||||
}
|
||||
if (reduce) {
|
||||
if (wire->width > 1)
|
||||
log_error("Multi-bit wand/wor unsupported (%s)\n",
|
||||
log_id(wire));
|
||||
|
||||
reduce->parameters["\\A_SIGNED"] = Const(0);
|
||||
reduce->parameters["\\A_WIDTH"] = Const(0);
|
||||
reduce->setPort("\\A", SigSpec());
|
||||
|
||||
reduce->parameters["\\Y_WIDTH"] = Const(1);
|
||||
reduce->setPort("\\Y", wire);
|
||||
wlogic_map[wire] = reduce;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto module : design_modules) {
|
||||
std::vector<SigSig> new_connections;
|
||||
for (auto &conn : module->connections())
|
||||
{
|
||||
SigSpec sig = conn.first;
|
||||
for (int i = 0; i < GetSize(sig); i++) {
|
||||
Wire *sigwire = sig[i].wire;
|
||||
if (sigwire == nullptr)
|
||||
continue;
|
||||
|
||||
if (sigwire->get_bool_attribute("\\wor") || sigwire->get_bool_attribute("\\wand")) {
|
||||
Cell *reduce = wlogic_map[sigwire];
|
||||
SigSpec reduce_in = reduce->getPort("\\A");
|
||||
int reduce_width = reduce->getParam("\\A_WIDTH").as_int();
|
||||
Wire *new_reduce_input = module->addWire(
|
||||
stringf("%s_in%d", reduce->name.c_str(), reduce_width));
|
||||
reduce_in.append(new_reduce_input);
|
||||
reduce->setPort("\\A", reduce_in);
|
||||
reduce->fixup_parameters();
|
||||
sig[i] = new_reduce_input;
|
||||
}
|
||||
}
|
||||
new_connections.push_back(SigSig(sig, conn.second));
|
||||
}
|
||||
module->new_connections(new_connections);
|
||||
}
|
||||
|
||||
for (auto module : design_modules)
|
||||
for (auto cell : module->cells())
|
||||
|
@ -996,6 +1051,27 @@ struct HierarchyPass : public Pass {
|
|||
cell->setPort(conn.first, sig);
|
||||
}
|
||||
|
||||
for (int i = 0; i < GetSize(sig); i++) {
|
||||
Wire *sigwire = sig[i].wire;
|
||||
if (sigwire == nullptr)
|
||||
continue;
|
||||
|
||||
if (sigwire->get_bool_attribute("\\wor") || sigwire->get_bool_attribute("\\wand")) {
|
||||
if (w->port_output && !w->port_input) {
|
||||
Cell *reduce = wlogic_map[sigwire];
|
||||
SigSpec reduce_in = reduce->getPort("\\A");
|
||||
int reduce_width = reduce->getParam("\\A_WIDTH").as_int();
|
||||
Wire *new_reduce_input = module->addWire(
|
||||
stringf("$%s_in%d", reduce->name.c_str(), reduce_width));
|
||||
reduce_in.append(new_reduce_input);
|
||||
reduce->setPort("\\A", reduce_in);
|
||||
reduce->fixup_parameters();
|
||||
sig[i] = new_reduce_input;
|
||||
}
|
||||
}
|
||||
}
|
||||
cell->setPort(conn.first, sig);
|
||||
|
||||
if (w->port_output && !w->port_input && sig.has_const())
|
||||
log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n",
|
||||
log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig));
|
||||
|
|
Loading…
Reference in New Issue