Merge pull request #2134 from whitequark/cxxrtl-opt-debug
[yosys.git] / frontends / verific / verific.cc
index ae5815f8e496f3efb78487423c05b01a52753f5e..a22a8a93d7d80de1f9aa9d9abbaf38ec9e7b59da 100644 (file)
@@ -149,13 +149,13 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj)
        return s;
 }
 
-void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj)
+void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj, Netlist *nl)
 {
        MapIter mi;
        Att *attr;
 
        if (obj->Linefile())
-               attributes["\\src"] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile()));
+               attributes[ID::src] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile()));
 
        // FIXME: Parse numeric attributes
        FOREACH_ATTRIBUTE(obj, mi, attr) {
@@ -163,6 +163,68 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
                        continue;
                attributes[RTLIL::escape_id(attr->Key())] = RTLIL::Const(std::string(attr->Value()));
        }
+
+       if (nl) {
+               auto type_range = nl->GetTypeRange(obj->Name());
+               if (!type_range)
+                       return;
+               if (!type_range->IsTypeEnum())
+                       return;
+               if (nl->IsFromVhdl() && strcmp(type_range->GetTypeName(), "STD_LOGIC") == 0)
+                       return;
+               auto type_name = type_range->GetTypeName();
+               if (!type_name)
+                       return;
+               attributes.emplace(ID::wiretype, RTLIL::escape_id(type_name));
+
+               MapIter mi;
+               const char *k, *v;
+               FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) {
+                       if (nl->IsFromVerilog()) {
+                               // Expect <decimal>'b<binary>
+                               auto p = strchr(v, '\'');
+                               if (p) {
+                                       if (*(p+1) != 'b')
+                                               p = nullptr;
+                                       else
+                                               for (auto q = p+2; *q != '\0'; q++)
+                                                       if (*q != '0' && *q != '1') {
+                                                               p = nullptr;
+                                                               break;
+                                                       }
+                               }
+                               if (p == nullptr)
+                                       log_error("Expected TypeRange value '%s' to be of form <decimal>'b<binary>.\n", v);
+                               attributes.emplace(stringf("\\enum_value_%s", p+2), RTLIL::escape_id(k));
+                       }
+                       else if (nl->IsFromVhdl()) {
+                               // Expect "<binary>"
+                               auto p = v;
+                               if (p) {
+                                       if (*p != '"')
+                                               p = nullptr;
+                                       else {
+                                               auto *q = p+1;
+                                               for (; *q != '"'; q++)
+                                                       if (*q != '0' && *q != '1') {
+                                                               p = nullptr;
+                                                               break;
+                                                       }
+                                               if (p && *(q+1) != '\0')
+                                                       p = nullptr;
+                                       }
+                               }
+                               if (p == nullptr)
+                                       log_error("Expected TypeRange value '%s' to be of form \"<binary>\".\n", v);
+                               auto l = strlen(p);
+                               auto q = (char*)malloc(l+1-2);
+                               strncpy(q, p+1, l-2);
+                               q[l-2] = '\0';
+                               attributes.emplace(stringf("\\enum_value_%s", q), RTLIL::escape_id(k));
+                               free(q);
+                       }
+               }
+       }
 }
 
 RTLIL::SigSpec VerificImporter::operatorInput(Instance *inst)
@@ -738,7 +800,7 @@ void VerificImporter::merge_past_ffs_clock(pool<RTLIL::Cell*> &candidates, SigBi
                SigSpec dbits;
 
                for (auto cell : candidates) {
-                       SigBit bit = sigmap(cell->getPort("\\D"));
+                       SigBit bit = sigmap(cell->getPort(ID::D));
                        dbits_db[bit].insert(cell);
                        dbits.append(bit);
                }
@@ -764,7 +826,7 @@ void VerificImporter::merge_past_ffs_clock(pool<RTLIL::Cell*> &candidates, SigBi
                                        if (verific_verbose)
                                                log("    replacing old ff %s on bit %d.\n", log_id(old_ff), i);
 
-                                       SigBit old_q = old_ff->getPort("\\Q");
+                                       SigBit old_q = old_ff->getPort(ID::Q);
                                        SigBit new_q = sig_q[i];
 
                                        sigmap.add(old_q, new_q);
@@ -783,8 +845,8 @@ void VerificImporter::merge_past_ffs(pool<RTLIL::Cell*> &candidates)
 
        for (auto cell : candidates)
        {
-               SigBit clock = cell->getPort("\\CLK");
-               bool clock_pol = cell->getParam("\\CLK_POLARITY").as_bool();
+               SigBit clock = cell->getPort(ID::CLK);
+               bool clock_pol = cell->getParam(ID::CLK_POLARITY).as_bool();
                database[make_pair(clock, int(clock_pol))].insert(cell);
        }
 
@@ -822,7 +884,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
 
        if (is_blackbox(nl)) {
                log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name));
-               module->set_bool_attribute("\\blackbox");
+               module->set_bool_attribute(ID::blackbox);
        } else {
                log("Importing module %s.\n", RTLIL::id2cstr(module->name));
        }
@@ -845,7 +907,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                        log("  importing port %s.\n", port->Name());
 
                RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(port->Name()));
-               import_attributes(wire->attributes, port);
+               import_attributes(wire->attributes, port, nl);
 
                wire->port_id = nl->IndexOf(port) + 1;
 
@@ -872,7 +934,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
 
                RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(portbus->Name()), portbus->Size());
                wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex());
-               import_attributes(wire->attributes, portbus);
+               import_attributes(wire->attributes, portbus, nl);
 
                if (portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN)
                        wire->port_input = true;
@@ -912,6 +974,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                        module->memories[memory->name] = memory;
 
                        int number_of_bits = net->Size();
+                       number_of_bits = 1 << ceil_log2(number_of_bits);
                        int bits_in_word = number_of_bits;
                        FOREACH_PORTREF_OF_NET(net, si, pr) {
                                if (pr->GetInst()->Type() == OPER_READ_PORT) {
@@ -952,17 +1015,17 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                                                ascii_initdata++;
                                        }
                                        if (initval_valid) {
-                                               RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit");
-                                               cell->parameters["\\WORDS"] = 1;
+                                               RTLIL::Cell *cell = module->addCell(new_verific_id(net), ID($meminit));
+                                               cell->parameters[ID::WORDS] = 1;
                                                if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound())
-                                                       cell->setPort("\\ADDR", word_idx);
+                                                       cell->setPort(ID::ADDR, word_idx);
                                                else
-                                                       cell->setPort("\\ADDR", memory->size - word_idx - 1);
-                                               cell->setPort("\\DATA", initval);
-                                               cell->parameters["\\MEMID"] = RTLIL::Const(memory->name.str());
-                                               cell->parameters["\\ABITS"] = 32;
-                                               cell->parameters["\\WIDTH"] = memory->width;
-                                               cell->parameters["\\PRIORITY"] = RTLIL::Const(autoidx-1);
+                                                       cell->setPort(ID::ADDR, memory->size - word_idx - 1);
+                                               cell->setPort(ID::DATA, initval);
+                                               cell->parameters[ID::MEMID] = RTLIL::Const(memory->name.str());
+                                               cell->parameters[ID::ABITS] = 32;
+                                               cell->parameters[ID::WIDTH] = memory->width;
+                                               cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1);
                                        }
                                }
                        }
@@ -1021,7 +1084,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                        log("  importing net %s as %s.\n", net->Name(), log_id(wire_name));
 
                RTLIL::Wire *wire = module->addWire(wire_name);
-               import_attributes(wire->attributes, net);
+               import_attributes(wire->attributes, net, nl);
 
                net_map[net] = wire;
        }
@@ -1046,7 +1109,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
 
                        RTLIL::Wire *wire = module->addWire(wire_name, netbus->Size());
                        wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex());
-                       import_attributes(wire->attributes, netbus);
+                       import_attributes(wire->attributes, netbus, nl);
 
                        RTLIL::Const initval = Const(State::Sx, GetSize(wire));
                        bool initval_valid = false;
@@ -1079,7 +1142,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                        }
 
                        if (initval_valid)
-                               wire->attributes["\\init"] = initval;
+                               wire->attributes[ID::init] = initval;
                }
                else
                {
@@ -1133,8 +1196,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                SigBit bit = net_map_at(it.first);
                log_assert(bit.wire);
 
-               if (bit.wire->attributes.count("\\init"))
-                       initval = bit.wire->attributes.at("\\init");
+               if (bit.wire->attributes.count(ID::init))
+                       initval = bit.wire->attributes.at(ID::init);
 
                while (GetSize(initval) < GetSize(bit.wire))
                        initval.bits.push_back(State::Sx);
@@ -1144,7 +1207,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                if (it.second == '1')
                        initval.bits.at(bit.offset) = State::S1;
 
-               bit.wire->attributes["\\init"] = initval;
+               bit.wire->attributes[ID::init] = initval;
        }
 
        for (auto net : anyconst_nets)
@@ -1199,64 +1262,63 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
 
                if (inst->Type() == OPER_READ_PORT)
                {
-                       RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetInput()->Name()));
+                       RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetInput()->Name()), nullptr);
+                       if (!memory)
+                               log_error("Memory net '%s' missing, possibly no driver, use verific -flatten.\n", inst->GetInput()->Name());
+
                        int numchunks = int(inst->OutputSize()) / memory->width;
                        int chunksbits = ceil_log2(numchunks);
 
-                       if ((numchunks * memory->width) != int(inst->OutputSize()) || (numchunks & (numchunks - 1)) != 0)
-                               log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name());
-
                        for (int i = 0; i < numchunks; i++)
                        {
                                RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)};
                                RTLIL::SigSpec data = operatorOutput(inst).extract(i * memory->width, memory->width);
 
                                RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name :
-                                               RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memrd");
-                               cell->parameters["\\MEMID"] = memory->name.str();
-                               cell->parameters["\\CLK_ENABLE"] = false;
-                               cell->parameters["\\CLK_POLARITY"] = true;
-                               cell->parameters["\\TRANSPARENT"] = false;
-                               cell->parameters["\\ABITS"] = GetSize(addr);
-                               cell->parameters["\\WIDTH"] = GetSize(data);
-                               cell->setPort("\\CLK", RTLIL::State::Sx);
-                               cell->setPort("\\EN", RTLIL::State::Sx);
-                               cell->setPort("\\ADDR", addr);
-                               cell->setPort("\\DATA", data);
+                                               RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memrd));
+                               cell->parameters[ID::MEMID] = memory->name.str();
+                               cell->parameters[ID::CLK_ENABLE] = false;
+                               cell->parameters[ID::CLK_POLARITY] = true;
+                               cell->parameters[ID::TRANSPARENT] = false;
+                               cell->parameters[ID::ABITS] = GetSize(addr);
+                               cell->parameters[ID::WIDTH] = GetSize(data);
+                               cell->setPort(ID::CLK, RTLIL::State::Sx);
+                               cell->setPort(ID::EN, RTLIL::State::Sx);
+                               cell->setPort(ID::ADDR, addr);
+                               cell->setPort(ID::DATA, data);
                        }
                        continue;
                }
 
                if (inst->Type() == OPER_WRITE_PORT || inst->Type() == OPER_CLOCKED_WRITE_PORT)
                {
-                       RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name()));
+                       RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name()), nullptr);
+                       if (!memory)
+                               log_error("Memory net '%s' missing, possibly no driver, use verific -flatten.\n", inst->GetInput()->Name());
                        int numchunks = int(inst->Input2Size()) / memory->width;
                        int chunksbits = ceil_log2(numchunks);
 
-                       if ((numchunks * memory->width) != int(inst->Input2Size()) || (numchunks & (numchunks - 1)) != 0)
-                               log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetOutput()->Name());
-
                        for (int i = 0; i < numchunks; i++)
                        {
                                RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)};
                                RTLIL::SigSpec data = operatorInput2(inst).extract(i * memory->width, memory->width);
 
                                RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name :
-                                               RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memwr");
-                               cell->parameters["\\MEMID"] = memory->name.str();
-                               cell->parameters["\\CLK_ENABLE"] = false;
-                               cell->parameters["\\CLK_POLARITY"] = true;
-                               cell->parameters["\\PRIORITY"] = 0;
-                               cell->parameters["\\ABITS"] = GetSize(addr);
-                               cell->parameters["\\WIDTH"] = GetSize(data);
-                               cell->setPort("\\EN", RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data)));
-                               cell->setPort("\\CLK", RTLIL::State::S0);
-                               cell->setPort("\\ADDR", addr);
-                               cell->setPort("\\DATA", data);
+                                               RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), ID($memwr));
+                               cell->parameters[ID::MEMID] = memory->name.str();
+                               cell->parameters[ID::CLK_ENABLE] = false;
+                               cell->parameters[ID::CLK_POLARITY] = true;
+                               cell->parameters[ID::PRIORITY] = 0;
+                               cell->parameters[ID::ABITS] = GetSize(addr);
+                               cell->parameters[ID::WIDTH] = GetSize(data);
+                               cell->setPort(ID::EN, RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data)));
+                               cell->setPort(ID::CLK, RTLIL::State::S0);
+                               cell->setPort(ID::ADDR, addr);
+                               cell->setPort(ID::DATA, data);
 
                                if (inst->Type() == OPER_CLOCKED_WRITE_PORT) {
-                                       cell->parameters["\\CLK_ENABLE"] = true;
-                                       cell->setPort("\\CLK", net_map_at(inst->GetClock()));
+                                       cell->parameters[ID::CLK_ENABLE] = true;
+                                       cell->setPort(ID::CLK, net_map_at(inst->GetClock()));
                                }
                        }
                        continue;
@@ -1431,7 +1493,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                RTLIL::Cell *cell = module->addCell(inst_name, inst_type);
 
                if (inst->IsPrimitive() && mode_keep)
-                       cell->attributes["\\keep"] = 1;
+                       cell->attributes[ID::keep] = 1;
 
                dict<IdString, vector<SigBit>> cell_port_conns;
 
@@ -1514,10 +1576,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
 
                for (auto wire : module->wires())
                {
-                       if (!wire->attributes.count("\\init"))
+                       if (!wire->attributes.count(ID::init))
                                continue;
 
-                       Const &initval = wire->attributes.at("\\init");
+                       Const &initval = wire->attributes.at(ID::init);
                        for (int i = 0; i < GetSize(initval); i++)
                        {
                                if (initval[i] != State::S0 && initval[i] != State::S1)
@@ -1528,7 +1590,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
                        }
 
                        if (initval.is_fully_undef())
-                               wire->attributes.erase("\\init");
+                               wire->attributes.erase(ID::init);
                }
        }
 }
@@ -1652,10 +1714,10 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const
        if (GetSize(init_value) != 0) {
                log_assert(GetSize(sig_q) == GetSize(init_value));
                if (sig_q.is_wire()) {
-                       sig_q.as_wire()->attributes["\\init"] = init_value;
+                       sig_q.as_wire()->attributes[ID::init] = init_value;
                } else {
                        Wire *w = module->addWire(NEW_ID, GetSize(sig_q));
-                       w->attributes["\\init"] = init_value;
+                       w->attributes[ID::init] = init_value;
                        module->connect(sig_q, w);
                        sig_q = w;
                }
@@ -2118,6 +2180,9 @@ struct VerificPass : public Pass {
                        RuntimeFlags::SetVar("vhdl_support_variable_slice", 1);
                        RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
 
+                       RuntimeFlags::SetVar("veri_preserve_assignments", 1);
+                       RuntimeFlags::SetVar("vhdl_preserve_assignments", 1);
+
                        // Workaround for VIPER #13851
                        RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1);