Merge remote-tracking branch 'origin/master' into clifford/specify
[yosys.git] / frontends / ast / genrtlil.cc
index 2d591b29d31b8294925afc770838437d78fb5f7d..92205b7ae69b5015150ac180525035fbf77bfce7 100644 (file)
@@ -525,7 +525,16 @@ struct AST_INTERNAL::ProcessGenerator
                                }
 
                                if (last_generated_case != NULL && ast->get_bool_attribute("\\full_case") && default_case == NULL) {
+                       #if 0
+                                       // this is a valid transformation, but as optimization it is premature.
+                                       // better: add a default case that assigns 'x' to everything, and let later
+                                       // optimizations take care of the rest
                                        last_generated_case->compare.clear();
+                       #else
+                                       default_case = new RTLIL::CaseRule;
+                                       addChunkActions(default_case->actions, this_case_eq_ltemp, SigSpec(State::Sx, GetSize(this_case_eq_rvalue)));
+                                       sw->cases.push_back(default_case);
+                       #endif
                                } else {
                                        if (default_case == NULL) {
                                                default_case = new RTLIL::CaseRule;
@@ -544,7 +553,11 @@ struct AST_INTERNAL::ProcessGenerator
                        break;
 
                case AST_WIRE:
-                       log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n");
+                       log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n");
+                       break;
+
+               case AST_ASSIGN:
+                       log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n");
                        break;
 
                case AST_PARAMETER:
@@ -632,6 +645,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
                        if (!id_ast->children[0]->range_valid)
                                log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str());
                        this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
+                       if (children.size() > 1)
+                               range = children[1];
                } else
                        log_file_error(filename, linenum, "Failed to detect width for identifier %s!\n", str.c_str());
                if (range) {
@@ -1409,10 +1424,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        if (GetSize(en) != 1)
                                en = current_module->ReduceBool(NEW_ID, en);
 
-                       std::stringstream sstr;
-                       sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++);
+                       IdString cellname;
+                       if (str.empty()) {
+                               std::stringstream sstr;
+                               sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++);
+                               cellname = sstr.str();
+                       } else {
+                               cellname = str;
+                       }
 
-                       RTLIL::Cell *cell = current_module->addCell(sstr.str(), celltype);
+                       RTLIL::Cell *cell = current_module->addCell(cellname, celltype);
                        cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
 
                        for (auto &attr : attributes) {
@@ -1502,9 +1523,29 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        }
                        for (auto &attr : attributes) {
                                if (attr.second->type != AST_CONSTANT)
-                                       log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
+                                       log_file_error(filename, linenum, "Attribute `%s' with non-constant value.\n", attr.first.c_str());
                                cell->attributes[attr.first] = attr.second->asAttrConst();
                        }
+                       if (cell->type.in("$specify2", "$specify3")) {
+                               int src_width = GetSize(cell->getPort("\\SRC"));
+                               int dst_width = GetSize(cell->getPort("\\DST"));
+                               bool full = cell->getParam("\\FULL").as_bool();
+                               if (!full && src_width != dst_width)
+                                       log_file_error(filename, linenum, "Parallel specify SRC width does not match DST width.\n");
+                               if (cell->type == "$specify3") {
+                                       int dat_width = GetSize(cell->getPort("\\DAT"));
+                                       if (dat_width != dst_width)
+                                               log_file_error(filename, linenum, "Specify DAT width does not match DST width.\n");
+                               }
+                               cell->setParam("\\SRC_WIDTH", Const(src_width));
+                               cell->setParam("\\DST_WIDTH", Const(dst_width));
+                       }
+                       if (cell->type == "$specrule") {
+                               int src_width = GetSize(cell->getPort("\\SRC"));
+                               int dst_width = GetSize(cell->getPort("\\DST"));
+                               cell->setParam("\\SRC_WIDTH", Const(src_width));
+                               cell->setParam("\\DST_WIDTH", Const(dst_width));
+                       }
                }
                break;