From 2ef2aa997cbe75732535946b25c35dcb3fe5eec4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 09:07:53 -0700 Subject: read_aiger to not require clk_name for latches, plus debug --- frontends/aiger/aigerparse.cc | 58 +++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 21 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d378a07b7..281e1cc9d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -495,8 +495,7 @@ void AigerReader::parse_aiger_ascii() // Parse latches RTLIL::Wire *clk_wire = nullptr; - if (L > 0) { - log_assert(clk_name != ""); + if (L > 0 && !clk_name.empty()) { clk_wire = module->wire(clk_name); log_assert(!clk_wire); log_debug("Creating %s\n", clk_name.c_str()); @@ -512,7 +511,10 @@ void AigerReader::parse_aiger_ascii() RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); + if (clk_wire) + module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); + else + module->addFfGate(NEW_ID, d_wire, q_wire); // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { @@ -620,8 +622,7 @@ void AigerReader::parse_aiger_binary() // Parse latches RTLIL::Wire *clk_wire = nullptr; - if (L > 0) { - log_assert(clk_name != ""); + if (L > 0 && !clk_name.empty()) { clk_wire = module->wire(clk_name); log_assert(!clk_wire); log_debug("Creating %s\n", clk_name.c_str()); @@ -637,7 +638,10 @@ void AigerReader::parse_aiger_binary() RTLIL::Wire *q_wire = createWireIfNotExists(module, l1); RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); - module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + if (clk_wire) + module->addDff(NEW_ID, clk_wire, d_wire, q_wire); + else + module->addFf(NEW_ID, d_wire, q_wire); // Reset logic is optional in AIGER 1.9 if (f.peek() == ' ') { @@ -731,7 +735,14 @@ void AigerReader::post_process() RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + RTLIL::Module* flop_module = nullptr; + if (box_module->attributes.count("\\abc_flop")) { + log_assert(flop_count < flopNum); + log_assert(box_module->name.begins_with("$__ABC_")); + flop_module = design->module("\\" + box_module->name.substr(7)); + log_assert(flop_module); + } + else if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -766,39 +777,36 @@ void AigerReader::post_process() } } - bool flop = box_module->attributes.count("\\abc_flop"); - log_assert(!flop || flop_count < flopNum); - // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) for (auto port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); - log_assert(w); + RTLIL::Wire* port = box_module->wire(port_name); + log_assert(port); RTLIL::SigSpec rhs; RTLIL::Wire* wire = nullptr; - for (int i = 0; i < GetSize(w); i++) { - if (w->port_input) { + for (int i = 0; i < GetSize(port); i++) { + if (port->port_input) { log_assert(co_count < outputs.size()); wire = outputs[co_count++]; log_assert(wire); log_assert(wire->port_output); wire->port_output = false; - if (flop && w->attributes.count("\\abc_flop_d")) { + if (flop_module && port->attributes.count("\\abc_flop_d")) { RTLIL::Wire* d = outputs[outputs.size() - flopNum + flop_count]; log_assert(d); log_assert(d->port_output); d->port_output = false; } } - if (w->port_output) { + if (port->port_output) { log_assert((piNum + ci_count) < inputs.size()); wire = inputs[piNum + ci_count++]; log_assert(wire); log_assert(wire->port_input); wire->port_input = false; - if (flop && w->attributes.count("\\abc_flop_q")) { + if (flop_module && port->attributes.count("\\abc_flop_q")) { wire = inputs[piNum - flopNum + flop_count]; log_assert(wire); log_assert(wire->port_input); @@ -807,10 +815,14 @@ void AigerReader::post_process() } rhs.append(wire); } - cell->setPort(port_name, rhs); + if (!flop_module || !port->attributes.count("\\abc_discard")) + cell->setPort(port_name, rhs); } - if (flop) flop_count++; + if (flop_module) { + flop_count++; + cell->type = flop_module->name; + } } dict wideports_cache; @@ -826,6 +838,7 @@ void AigerReader::post_process() RTLIL::Wire* wire = inputs[variable]; log_assert(wire); log_assert(wire->port_input); + log_debug("Renaming input %s", log_id(wire)); if (index == 0) { // Cope with the fact that a CI might be identical @@ -852,12 +865,14 @@ void AigerReader::post_process() wire->port_input = false; } } + log_debug(" -> %s\n", log_id(wire)); } else if (type == "output") { log_assert(static_cast(variable + co_count) < outputs.size()); RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); + log_debug("Renaming output %s", log_id(wire)); if (index == 0) { // Cope with the fact that a CO might be identical @@ -904,6 +919,7 @@ void AigerReader::post_process() wire->port_output = false; } } + log_debug(" -> %s\n", log_id(wire)); } else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); @@ -1009,8 +1025,8 @@ struct AigerFrontend : public Frontend { log(" Name of module to be created (default: )\n"); log("\n"); log(" -clk_name \n"); - log(" AIGER latches to be transformed into posedge DFFs clocked by wire of"); - log(" this name (default: clk)\n"); + log(" If specified, AIGER latches to be transformed into $_DFF_P_ cells\n" + log(" clocked by wire of this name. Otherwise, $_FF_ cells will be used.\n"); log("\n"); log(" -map \n"); log(" read file with port and latch symbols\n"); -- cgit v1.2.3 From 7a3c403ba0e411c990be59da44e1decb6aafc8f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 09:10:01 -0700 Subject: Missing close bracket --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 281e1cc9d..d0d2ffdba 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -1025,7 +1025,7 @@ struct AigerFrontend : public Frontend { log(" Name of module to be created (default: )\n"); log("\n"); log(" -clk_name \n"); - log(" If specified, AIGER latches to be transformed into $_DFF_P_ cells\n" + log(" If specified, AIGER latches to be transformed into $_DFF_P_ cells\n"); log(" clocked by wire of this name. Otherwise, $_FF_ cells will be used.\n"); log("\n"); log(" -map \n"); -- cgit v1.2.3 From b706ae82de2fa82b68c327740820c03cc203a217 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 12:42:18 -0700 Subject: Fix log_debug messages --- frontends/aiger/aigerparse.cc | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d0d2ffdba..833c0023b 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -429,6 +429,7 @@ void AigerReader::parse_xaiger() else if (c == 'r') { uint32_t dataSize = parse_xaiger_literal(f); flopNum = parse_xaiger_literal(f); + log_debug("flopNum: %u\n", flopNum); log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); f.ignore(flopNum * sizeof(uint32_t)); } @@ -450,7 +451,7 @@ void AigerReader::parse_xaiger() uint32_t poNum = parse_xaiger_literal(f); log_debug("poNum = %u\n", poNum); uint32_t boxNum = parse_xaiger_literal(f); - log_debug("boxNum = %u\n", poNum); + log_debug("boxNum = %u\n", boxNum); for (unsigned i = 0; i < boxNum; i++) { f.ignore(2*sizeof(uint32_t)); uint32_t boxUniqueId = parse_xaiger_literal(f); @@ -777,51 +778,56 @@ void AigerReader::post_process() } } + RTLIL::Wire *d = nullptr; + RTLIL::Wire *q = nullptr; // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) for (auto port_name : box_module->ports) { RTLIL::Wire* port = box_module->wire(port_name); log_assert(port); RTLIL::SigSpec rhs; - RTLIL::Wire* wire = nullptr; for (int i = 0; i < GetSize(port); i++) { + RTLIL::Wire* wire = nullptr; if (port->port_input) { - log_assert(co_count < outputs.size()); - wire = outputs[co_count++]; - log_assert(wire); - log_assert(wire->port_output); - wire->port_output = false; - if (flop_module && port->attributes.count("\\abc_flop_d")) { - RTLIL::Wire* d = outputs[outputs.size() - flopNum + flop_count]; + log_assert(!d); + d = outputs[outputs.size() - flopNum + flop_count]; log_assert(d); log_assert(d->port_output); d->port_output = false; } + + log_assert(co_count < outputs.size()); + wire = outputs[co_count++]; + log_assert(wire); + log_assert(wire->port_output); + wire->port_output = false; } if (port->port_output) { + if (flop_module && port->attributes.count("\\abc_flop_q")) { + log_assert(!q); + q = inputs[piNum - flopNum + flop_count]; + log_assert(q); + log_assert(q->port_input); + q->port_input = false; + } + log_assert((piNum + ci_count) < inputs.size()); wire = inputs[piNum + ci_count++]; log_assert(wire); log_assert(wire->port_input); wire->port_input = false; - - if (flop_module && port->attributes.count("\\abc_flop_q")) { - wire = inputs[piNum - flopNum + flop_count]; - log_assert(wire); - log_assert(wire->port_input); - wire->port_input = false; - } } rhs.append(wire); } if (!flop_module || !port->attributes.count("\\abc_discard")) cell->setPort(port_name, rhs); } - if (flop_module) { flop_count++; cell->type = flop_module->name; + //module->addFfGate(NEW_ID, d1 q); + module->connect(q, d); } } -- cgit v1.2.3 From c04921c3a8391d2335fab42ef354bb2bb2f3ac2a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 18:13:44 -0700 Subject: Fix debug message --- frontends/aiger/aigerparse.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 833c0023b..d2657c9da 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -900,6 +900,7 @@ void AigerReader::post_process() else { wire->port_output = false; module->connect(wire, existing); + wire = existing; } } else if (index > 0) { -- cgit v1.2.3 From 3d1185b835e16cc0613aa7a31e810dd6da69599f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 15 Jun 2019 22:41:42 -0700 Subject: Read init from outputs --- frontends/aiger/aigerparse.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d2657c9da..5a6db8481 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -927,6 +927,10 @@ void AigerReader::post_process() } } log_debug(" -> %s\n", log_id(wire)); + int init; + mf >> init; + if (init < 2) + wire->attributes["\\init"] = init; } else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); -- cgit v1.2.3 From 0c59bc0b75ba2985e6ae0806d410fe2fa1c94e37 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 10:42:00 -0700 Subject: Cleanup --- frontends/aiger/aigerparse.cc | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 5a6db8481..60cbde857 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -737,11 +737,13 @@ void AigerReader::post_process() log_assert(box_module); RTLIL::Module* flop_module = nullptr; - if (box_module->attributes.count("\\abc_flop")) { + auto flop_module_name = box_module->attributes.at("\\abc_flop", RTLIL::Const()); + RTLIL::IdString flop_past_q; + if (flop_module_name.size() > 0) { log_assert(flop_count < flopNum); - log_assert(box_module->name.begins_with("$__ABC_")); - flop_module = design->module("\\" + box_module->name.substr(7)); + flop_module = design->module(RTLIL::escape_id(flop_module_name.decode_string())); log_assert(flop_module); + flop_past_q = box_module->attributes.at("\\abc_flop_past_q").decode_string(); } else if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; @@ -778,8 +780,6 @@ void AigerReader::post_process() } } - RTLIL::Wire *d = nullptr; - RTLIL::Wire *q = nullptr; // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) for (auto port_name : box_module->ports) { @@ -789,14 +789,6 @@ void AigerReader::post_process() for (int i = 0; i < GetSize(port); i++) { RTLIL::Wire* wire = nullptr; if (port->port_input) { - if (flop_module && port->attributes.count("\\abc_flop_d")) { - log_assert(!d); - d = outputs[outputs.size() - flopNum + flop_count]; - log_assert(d); - log_assert(d->port_output); - d->port_output = false; - } - log_assert(co_count < outputs.size()); wire = outputs[co_count++]; log_assert(wire); @@ -804,14 +796,6 @@ void AigerReader::post_process() wire->port_output = false; } if (port->port_output) { - if (flop_module && port->attributes.count("\\abc_flop_q")) { - log_assert(!q); - q = inputs[piNum - flopNum + flop_count]; - log_assert(q); - log_assert(q->port_input); - q->port_input = false; - } - log_assert((piNum + ci_count) < inputs.size()); wire = inputs[piNum + ci_count++]; log_assert(wire); @@ -820,13 +804,24 @@ void AigerReader::post_process() } rhs.append(wire); } - if (!flop_module || !port->attributes.count("\\abc_discard")) + + if (!flop_module || port_name != flop_past_q) cell->setPort(port_name, rhs); } + if (flop_module) { + RTLIL::Wire *d = outputs[outputs.size() - flopNum + flop_count]; + log_assert(d); + log_assert(d->port_output); + d->port_output = false; + + RTLIL::Wire *q = inputs[piNum - flopNum + flop_count]; + log_assert(q); + log_assert(q->port_input); + q->port_input = false; + flop_count++; cell->type = flop_module->name; - //module->addFfGate(NEW_ID, d1 q); module->connect(q, d); } } -- cgit v1.2.3 From ac5f3d500db46a4312d77f43fded2feb25545a3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 11:10:44 -0700 Subject: Fix spacing --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7f81a4c89..57a164f1b 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -756,7 +756,7 @@ void AigerReader::post_process() log_assert(flop_module); flop_past_q = box_module->attributes.at("\\abc_flop_past_q").decode_string(); } - else if (seen_boxes.insert(cell->type).second) { + else if (seen_boxes.insert(cell->type).second) { auto it = box_module->attributes.find("\\abc_carry"); if (it != box_module->attributes.end()) { RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; -- cgit v1.2.3 From a31e17182d7f9437fb78f5018dfccbd66d9704ea Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 1 Jul 2019 11:50:34 -0700 Subject: Refactor and cope with new abc_flop format --- frontends/aiger/aigerparse.cc | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 57a164f1b..30e35da01 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -742,22 +742,29 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { pool seen_boxes; + dict> flop_data; unsigned ci_count = 0, co_count = 0, flop_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); RTLIL::Module* flop_module = nullptr; - auto flop_module_name = box_module->attributes.at("\\abc_flop", RTLIL::Const()); RTLIL::IdString flop_past_q; - if (flop_module_name.size() > 0) { - log_assert(flop_count < flopNum); - flop_module = design->module(RTLIL::escape_id(flop_module_name.decode_string())); - log_assert(flop_module); - flop_past_q = box_module->attributes.at("\\abc_flop_past_q").decode_string(); - } - else if (seen_boxes.insert(cell->type).second) { - auto it = box_module->attributes.find("\\abc_carry"); + if (seen_boxes.insert(cell->type).second) { + auto it = box_module->attributes.find("\\abc_flop"); + if (it != box_module->attributes.end()) { + log_assert(flop_count < flopNum); + std::string abc_flop = it->second.decode_string(); + auto pos = abc_flop.find(','); + log_assert(pos != std::string::npos); + flop_module = design->module(RTLIL::escape_id(abc_flop.substr(0, pos))); + log_assert(flop_module); + pos = abc_flop.rfind(','); + log_assert(pos != std::string::npos); + flop_past_q = RTLIL::escape_id(abc_flop.substr(pos+1)); + flop_data[cell->type] = std::make_pair(flop_module, flop_past_q); + } + it = box_module->attributes.find("\\abc_carry"); if (it != box_module->attributes.end()) { RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; auto carry_in_out = it->second.decode_string(); @@ -796,6 +803,11 @@ void AigerReader::post_process() carry_out->port_id = ports.size(); } } + else { + auto it = flop_data.find(cell->type); + if (it != flop_data.end()) + std::tie(flop_module,flop_past_q) = it->second; + } // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) -- cgit v1.2.3 From a092c48f036b71cc4014ec6f2865297d49589d40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 17:34:51 -0700 Subject: Use split_tokens() --- frontends/aiger/aigerparse.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 30e35da01..35b7f6a97 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -754,14 +754,14 @@ void AigerReader::post_process() auto it = box_module->attributes.find("\\abc_flop"); if (it != box_module->attributes.end()) { log_assert(flop_count < flopNum); - std::string abc_flop = it->second.decode_string(); - auto pos = abc_flop.find(','); - log_assert(pos != std::string::npos); - flop_module = design->module(RTLIL::escape_id(abc_flop.substr(0, pos))); - log_assert(flop_module); - pos = abc_flop.rfind(','); - log_assert(pos != std::string::npos); - flop_past_q = RTLIL::escape_id(abc_flop.substr(pos+1)); + auto abc_flop = it->second.decode_string(); + auto tokens = split_tokens(abc_flop, ","); + if (tokens.size() != 4) + log_error("'abc_flop' attribute on module '%s' does not contain exactly four comma-separated tokens.\n", log_id(cell->type)); + flop_module = design->module(RTLIL::escape_id(tokens[0])); + if (!flop_module) + log_error("First token '%s' in 'abc_flop' attribute on module '%s' is not a valid module.\n", tokens[0].c_str(), log_id(cell->type)); + flop_past_q = RTLIL::escape_id(tokens[3]); flop_data[cell->type] = std::make_pair(flop_module, flop_past_q); } it = box_module->attributes.find("\\abc_carry"); -- cgit v1.2.3 From 4a995c5d80735baf1431a088c2faf81eb75fdaf6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 17:54:56 -0700 Subject: Change how to specify flops to ABC again --- frontends/aiger/aigerparse.cc | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 35b7f6a97..11c5e3570 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -742,27 +742,23 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { pool seen_boxes; - dict> flop_data; + dict flop_data; unsigned ci_count = 0, co_count = 0, flop_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); RTLIL::Module* flop_module = nullptr; - RTLIL::IdString flop_past_q; + const RTLIL::IdString flop_past_q = RTLIL::escape_id("\\$pastQ"); if (seen_boxes.insert(cell->type).second) { auto it = box_module->attributes.find("\\abc_flop"); if (it != box_module->attributes.end()) { log_assert(flop_count < flopNum); auto abc_flop = it->second.decode_string(); - auto tokens = split_tokens(abc_flop, ","); - if (tokens.size() != 4) - log_error("'abc_flop' attribute on module '%s' does not contain exactly four comma-separated tokens.\n", log_id(cell->type)); - flop_module = design->module(RTLIL::escape_id(tokens[0])); + flop_module = design->module(RTLIL::escape_id(abc_flop)); if (!flop_module) - log_error("First token '%s' in 'abc_flop' attribute on module '%s' is not a valid module.\n", tokens[0].c_str(), log_id(cell->type)); - flop_past_q = RTLIL::escape_id(tokens[3]); - flop_data[cell->type] = std::make_pair(flop_module, flop_past_q); + log_error("'abc_flop' attribute value '%s' on module '%s' is not a valid module.\n", abc_flop.c_str(), log_id(cell->type)); + flop_data[cell->type] = flop_module; } it = box_module->attributes.find("\\abc_carry"); if (it != box_module->attributes.end()) { @@ -806,7 +802,7 @@ void AigerReader::post_process() else { auto it = flop_data.find(cell->type); if (it != flop_data.end()) - std::tie(flop_module,flop_past_q) = it->second; + flop_module = it->second; } // NB: Assume box_module->ports are sorted alphabetically -- cgit v1.2.3 From f8f0ffe786eabd016e0f9a0e4f4de10743638cdf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Jul 2019 18:56:50 -0700 Subject: Small opt --- frontends/aiger/aigerparse.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 11c5e3570..b599160cf 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -749,7 +749,6 @@ void AigerReader::post_process() log_assert(box_module); RTLIL::Module* flop_module = nullptr; - const RTLIL::IdString flop_past_q = RTLIL::escape_id("\\$pastQ"); if (seen_boxes.insert(cell->type).second) { auto it = box_module->attributes.find("\\abc_flop"); if (it != box_module->attributes.end()) { @@ -830,7 +829,7 @@ void AigerReader::post_process() rhs.append(wire); } - if (!flop_module || port_name != flop_past_q) + if (!flop_module || port_name != "\\$pastQ") cell->setPort(port_name, rhs); } -- cgit v1.2.3 From bd198aa803bdfc3b21bfa920822805df992e3120 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Jul 2019 10:07:14 -0700 Subject: Missing debug message --- frontends/aiger/aigerparse.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b599160cf..77ef75cd5 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -901,6 +901,7 @@ void AigerReader::post_process() wire->port_output = false; continue; } + log_debug("Renaming output %s", log_id(wire)); if (index == 0) { // Cope with the fact that a CO might be identical -- cgit v1.2.3 From a314565ad448c1d5a76604bbd25ac2c901c08f8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Jul 2019 10:52:45 -0700 Subject: Short out async box --- frontends/aiger/aigerparse.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 77ef75cd5..b984e846a 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -741,6 +741,9 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { + const RTLIL::Wire* n0 = module->wire("\\__0__"); + const RTLIL::Wire* n1 = module->wire("\\__1__"); + pool seen_boxes; dict flop_data; unsigned ci_count = 0, co_count = 0, flop_count = 0; @@ -847,6 +850,17 @@ void AigerReader::post_process() flop_count++; cell->type = flop_module->name; module->connect(q, d); + continue; + } + + // Remove the async mux by shorting out its input and output + if (cell->type == "$__ABC_ASYNC") { + RTLIL::Wire* A = cell->getPort("\\A").as_wire(); + if (A == n0 || A == n1) A = nullptr; + auto it = cell->connections_.find("\\Y"); + log_assert(it != cell->connections_.end()); + module->connect(it->second, A); + cell->connections_.erase(it); } } -- cgit v1.2.3 From 9bfe924e17a87fac8a35fcb7ff5e067f6c520e07 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 19 Aug 2019 09:40:01 -0700 Subject: Set abc_flop and use it in toposort --- frontends/aiger/aigerparse.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index f2b38da67..6fd9e0432 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -840,6 +840,7 @@ void AigerReader::post_process() flop_count++; cell->type = flop_module->name; module->connect(q, d); + cell->set_bool_attribute("\\abc_flop"); continue; } -- cgit v1.2.3 From be9e4f1b674ef4fb3f02e99efcfda04ea27b2a68 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 12:39:11 -0700 Subject: Use abc_{map,unmap,model}.v --- frontends/aiger/aigerparse.cc | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index cb4ec6183..7a467b91e 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -731,28 +731,21 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { - const RTLIL::Wire* n0 = module->wire("\\__0__"); - const RTLIL::Wire* n1 = module->wire("\\__1__"); - pool seen_boxes; - dict flop_data; + pool flops; unsigned ci_count = 0, co_count = 0, flop_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); - RTLIL::Module* flop_module = nullptr; + bool is_flop = false; if (seen_boxes.insert(cell->type).second) { - auto it = box_module->attributes.find("\\abc_flop"); - if (it != box_module->attributes.end()) { + if (box_module->attributes.count("\\abc_flop")) { log_assert(flop_count < flopNum); - auto abc_flop = it->second.decode_string(); - flop_module = design->module(RTLIL::escape_id(abc_flop)); - if (!flop_module) - log_error("'abc_flop' attribute value '%s' on module '%s' is not a valid module.\n", abc_flop.c_str(), log_id(cell->type)); - flop_data[cell->type] = flop_module; + flops.insert(cell->type); + is_flop = true; } - it = box_module->attributes.find("\\abc_carry"); + auto it = box_module->attributes.find("\\abc_carry"); if (it != box_module->attributes.end()) { RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; auto carry_in_out = it->second.decode_string(); @@ -791,11 +784,8 @@ void AigerReader::post_process() carry_out->port_id = ports.size(); } } - else { - auto it = flop_data.find(cell->type); - if (it != flop_data.end()) - flop_module = it->second; - } + else + is_flop = flops.count(cell->type); // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) @@ -822,11 +812,11 @@ void AigerReader::post_process() rhs.append(wire); } - if (!flop_module || port_name != "\\$pastQ") + if (!is_flop || port_name != "\\$pastQ") cell->setPort(port_name, rhs); } - if (flop_module) { + if (is_flop) { RTLIL::Wire *d = outputs[outputs.size() - flopNum + flop_count]; log_assert(d); log_assert(d->port_output); @@ -838,21 +828,10 @@ void AigerReader::post_process() q->port_input = false; flop_count++; - cell->type = flop_module->name; module->connect(q, d); cell->set_bool_attribute("\\abc_flop"); continue; } - - // Remove the async mux by shorting out its input and output - if (cell->type == "$__ABC_ASYNC") { - RTLIL::Wire* A = cell->getPort("\\A").as_wire(); - if (A == n0 || A == n1) A = nullptr; - auto it = cell->connections_.find("\\Y"); - log_assert(it != cell->connections_.end()); - module->connect(it->second, A); - cell->connections_.erase(it); - } } dict wideports_cache; -- cgit v1.2.3 From 091bf4a18b2f4bf84fe62b61577c88d961468b3c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 20 Aug 2019 18:16:37 -0700 Subject: Remove sequential extension --- frontends/aiger/aigerparse.cc | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7a467b91e..e8ee487e5 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -732,19 +732,12 @@ void AigerReader::parse_aiger_binary() void AigerReader::post_process() { pool seen_boxes; - pool flops; - unsigned ci_count = 0, co_count = 0, flop_count = 0; + unsigned ci_count = 0, co_count = 0; for (auto cell : boxes) { RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); - bool is_flop = false; if (seen_boxes.insert(cell->type).second) { - if (box_module->attributes.count("\\abc_flop")) { - log_assert(flop_count < flopNum); - flops.insert(cell->type); - is_flop = true; - } auto it = box_module->attributes.find("\\abc_carry"); if (it != box_module->attributes.end()) { RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; @@ -784,8 +777,6 @@ void AigerReader::post_process() carry_out->port_id = ports.size(); } } - else - is_flop = flops.count(cell->type); // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) @@ -812,25 +803,7 @@ void AigerReader::post_process() rhs.append(wire); } - if (!is_flop || port_name != "\\$pastQ") - cell->setPort(port_name, rhs); - } - - if (is_flop) { - RTLIL::Wire *d = outputs[outputs.size() - flopNum + flop_count]; - log_assert(d); - log_assert(d->port_output); - d->port_output = false; - - RTLIL::Wire *q = inputs[piNum - flopNum + flop_count]; - log_assert(q); - log_assert(q->port_input); - q->port_input = false; - - flop_count++; - module->connect(q, d); - cell->set_bool_attribute("\\abc_flop"); - continue; + cell->setPort(port_name, rhs); } } @@ -934,10 +907,6 @@ void AigerReader::post_process() } } log_debug(" -> %s\n", log_id(wire)); - int init; - mf >> init; - if (init < 2) - wire->attributes["\\init"] = init; } else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); -- cgit v1.2.3 From 34ae29295db53289e786c0279ed00474cf0294d3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 28 Aug 2019 19:59:09 -0700 Subject: read_verilog -defer should still populate module attributes --- frontends/ast/ast.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 82283fb5b..6a91c418b 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1073,11 +1073,6 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast ignoreThisSignalsInInitial = RTLIL::SigSpec(); - for (auto &attr : ast->attributes) { - if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); - current_module->attributes[attr.first] = attr.second->asAttrConst(); - } for (size_t i = 0; i < ast->children.size(); i++) { AstNode *node = ast->children[i]; if (node->type == AST_WIRE || node->type == AST_MEMORY) @@ -1100,6 +1095,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast ignoreThisSignalsInInitial = RTLIL::SigSpec(); } + for (auto &attr : ast->attributes) { + if (attr.second->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + current_module->attributes[attr.first] = attr.second->asAttrConst(); + } + if (ast->type == AST_INTERFACE) current_module->set_bool_attribute("\\is_interface"); current_module->ast = ast_before_simplify; -- cgit v1.2.3 From 6510297712729f9742d00f6a4cd4fc3a0e530758 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 29 Aug 2019 09:02:10 -0700 Subject: Restore non-deferred code, deferred case to ignore non constant attr --- frontends/ast/ast.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 6a91c418b..01e865557 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1073,6 +1073,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast ignoreThisSignalsInInitial = RTLIL::SigSpec(); + for (auto &attr : ast->attributes) { + if (attr.second->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + current_module->attributes[attr.first] = attr.second->asAttrConst(); + } + for (size_t i = 0; i < ast->children.size(); i++) { AstNode *node = ast->children[i]; if (node->type == AST_WIRE || node->type == AST_MEMORY) @@ -1094,11 +1100,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast ignoreThisSignalsInInitial = RTLIL::SigSpec(); } - - for (auto &attr : ast->attributes) { - if (attr.second->type != AST_CONSTANT) - log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); - current_module->attributes[attr.first] = attr.second->asAttrConst(); + else { + for (auto &attr : ast->attributes) { + if (attr.second->type != AST_CONSTANT) + continue; + current_module->attributes[attr.first] = attr.second->asAttrConst(); + } } if (ast->type == AST_INTERFACE) -- cgit v1.2.3 From 83ffec26cbda434b31a2bbd004213a538bf3e6e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 29 Aug 2019 09:08:58 -0700 Subject: Remove newline --- frontends/ast/ast.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 01e865557..a3a78e414 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1078,7 +1078,6 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); current_module->attributes[attr.first] = attr.second->asAttrConst(); } - for (size_t i = 0; i < ast->children.size(); i++) { AstNode *node = ast->children[i]; if (node->type == AST_WIRE || node->type == AST_MEMORY) -- cgit v1.2.3 From 25e5fbac9096a872f7be1a481e6798103f40ccf5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 2 Sep 2019 22:56:38 +0200 Subject: Properly construct $live and $fair cells from "if (...) assume/assert (s_eventually ...)" Fixes https://github.com/YosysHQ/SymbiYosys/issues/59 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 86dd80c65..52fcf3ee7 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1530,10 +1530,16 @@ skip_dynamic_range_lvalue_expansion:; current_scope[wire_en->str] = wire_en; while (wire_en->simplify(true, false, false, 1, -1, false, false)) { } - std::vector x_bit; - x_bit.push_back(RTLIL::State::Sx); + AstNode *check_defval; + if (type == AST_LIVE || type == AST_FAIR) { + check_defval = new AstNode(AST_REDUCE_BOOL, children[0]->clone()); + } else { + std::vector x_bit; + x_bit.push_back(RTLIL::State::Sx); + check_defval = mkconst_bits(x_bit, false); + } - AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false)); + AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), check_defval); assign_check->children[0]->str = id_check; assign_check->children[0]->was_checked = true; @@ -1546,9 +1552,13 @@ skip_dynamic_range_lvalue_expansion:; default_signals->children.push_back(assign_en); current_top_block->children.insert(current_top_block->children.begin(), default_signals); - assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone())); - assign_check->children[0]->str = id_check; - assign_check->children[0]->was_checked = true; + if (type == AST_LIVE || type == AST_FAIR) { + assign_check = nullptr; + } else { + assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone())); + assign_check->children[0]->str = id_check; + assign_check->children[0]->was_checked = true; + } if (current_always == nullptr || current_always->type != AST_INITIAL) { assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1)); @@ -1560,7 +1570,8 @@ skip_dynamic_range_lvalue_expansion:; assign_en->children[0]->was_checked = true; newNode = new AstNode(AST_BLOCK); - newNode->children.push_back(assign_check); + if (assign_check != nullptr) + newNode->children.push_back(assign_check); newNode->children.push_back(assign_en); AstNode *assertnode = new AstNode(type); -- cgit v1.2.3 From d3eea82bc27f6e54b6c1e05a73be8456344ec8b7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 4 Sep 2019 15:21:39 -0700 Subject: Revert "parse_xaiger() to do "clean -purge"" This reverts commit 5d16bf831688ff665b0ec2abd6835b71320b2db5. --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 2e1fb8fad..06522939f 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -974,7 +974,7 @@ void AigerReader::post_process() // operate (and run checks on) this one module RTLIL::Design *mapped_design = new RTLIL::Design; mapped_design->add(module); - Pass::call(mapped_design, "clean -purge"); + Pass::call(mapped_design, "clean"); mapped_design->modules_.erase(module->name); delete mapped_design; -- cgit v1.2.3 From 7eb593829f62476598bb15c2fb903d50108e5274 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 12 Sep 2019 09:43:19 +0200 Subject: Fix lexing of integer literals, fixes #1364 Signed-off-by: Clifford Wolf --- frontends/verilog/const2ast.cc | 4 ++-- frontends/verilog/verilog_lexer.l | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 4bf5b1cf5..5da88a93f 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -199,13 +199,13 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn if (str == endptr) len_in_bits = -1; - // The "'s?[bodhBODH]" syntax + // The "'[sS]?[bodhBODH]" syntax if (*endptr == '\'') { std::vector data; bool is_signed = false; bool is_unsized = len_in_bits < 0; - if (*(endptr+1) == 's') { + if (*(endptr+1) == 's' || *(endptr+1) == 'S') { is_signed = true; endptr++; } diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 57e55b1f4..e344ffd4f 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -239,7 +239,7 @@ YOSYS_NAMESPACE_END return TOK_CONSTVAL; } -[0-9]*[ \t]*\'s?[bodhBODH]*[ \t\r\n]*[0-9a-fA-FzxZX?_]+ { +[0-9]*[ \t]*\'[sS]?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ { frontend_verilog_yylval.string = new std::string(yytext); return TOK_CONSTVAL; } -- cgit v1.2.3 From 855e6a9b9172e6817c9ff57f7041b09a1cc0367e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 13 Sep 2019 10:19:58 +0200 Subject: Fix lexing of integer literals without radix Signed-off-by: Clifford Wolf --- frontends/verilog/verilog_lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index e344ffd4f..4acfb414d 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -239,7 +239,7 @@ YOSYS_NAMESPACE_END return TOK_CONSTVAL; } -[0-9]*[ \t]*\'[sS]?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ { +[0-9]*[ \t]*\'[sS]?[bodhBODH]?[ \t\r\n]*[0-9a-fA-FzxZX?_]+ { frontend_verilog_yylval.string = new std::string(yytext); return TOK_CONSTVAL; } -- cgit v1.2.3 From a67d63714be52e4a4f789c2a82b6283748db8902 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 13 Sep 2019 13:39:39 +0200 Subject: Fix handling of z_digit "?" and fix optimization of cmp with "z" Signed-off-by: Clifford Wolf --- frontends/verilog/const2ast.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 5da88a93f..49281f7e7 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -85,10 +85,8 @@ static void my_strtobin(std::vector &data, const char *str, int le digits.push_back(10 + *str - 'A'); else if (*str == 'x' || *str == 'X') digits.push_back(0xf0); - else if (*str == 'z' || *str == 'Z') + else if (*str == 'z' || *str == 'Z' || *str == '?') digits.push_back(0xf1); - else if (*str == '?') - digits.push_back(0xf2); str++; } @@ -112,8 +110,6 @@ static void my_strtobin(std::vector &data, const char *str, int le data.push_back(case_type == 'x' ? RTLIL::Sa : RTLIL::Sx); else if (*it == 0xf1) data.push_back(case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz); - else if (*it == 0xf2) - data.push_back(RTLIL::Sa); else data.push_back((*it & bitmask) ? State::S1 : State::S0); } -- cgit v1.2.3 From 25b08b1afd87f6c2e6a6c1318bc790b4a929b7f5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 16 Sep 2019 11:25:16 +0200 Subject: Fix handling of range selects on loop variables, fixes #1372 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 52fcf3ee7..b1ee22f42 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2895,8 +2895,15 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map &name_map) { if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) { - current_scope[index_var]->children[0]->cloneInto(this); - return; + if (children.empty()) { + current_scope[index_var]->children[0]->cloneInto(this); + } else { + AstNode *p = new AstNode(AST_LOCALPARAM, current_scope[index_var]->children[0]->clone()); + p->str = stringf("$genval$%d", autoidx++); + current_ast_mod->children.push_back(p); + str = p->str; + id2ast = p; + } } if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) -- cgit v1.2.3 From 8da0888bf6ae4c975c6d3b0c9a656bc10e1283e4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 20 Sep 2019 12:16:20 +0200 Subject: Fix handling of read_verilog config in AstModule::reprocess_module(), fixes #1360 Signed-off-by: Clifford Wolf --- frontends/ast/ast.cc | 47 +++++++++++++++++++++++++++++------------------ frontends/ast/ast.h | 1 + 2 files changed, 30 insertions(+), 18 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index a3a78e414..21279cbfa 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -158,6 +158,11 @@ std::string AST::type2str(AstNodeType type) X(AST_POSEDGE) X(AST_NEGEDGE) X(AST_EDGE) + X(AST_INTERFACE) + X(AST_INTERFACEPORT) + X(AST_INTERFACEPORTTYPE) + X(AST_MODPORT) + X(AST_MODPORTMEMBER) X(AST_PACKAGE) #undef X default: @@ -1291,6 +1296,8 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule // from AST. The interface members are copied into the AST module with the prefix of the interface. void AstModule::reprocess_module(RTLIL::Design *design, dict local_interfaces) { + loadconfig(); + bool is_top = false; AstNode *new_ast = ast->clone(); for (auto &intf : local_interfaces) { @@ -1474,24 +1481,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dictclone(); @@ -1572,6 +1562,27 @@ RTLIL::Module *AstModule::clone() const return new_mod; } +void AstModule::loadconfig() const +{ + current_ast = NULL; + flag_dump_ast1 = false; + flag_dump_ast2 = false; + flag_dump_vlog1 = false; + flag_dump_vlog2 = false; + flag_nolatches = nolatches; + flag_nomeminit = nomeminit; + flag_nomem2reg = nomem2reg; + flag_mem2reg = mem2reg; + flag_noblackbox = noblackbox; + flag_lib = lib; + flag_nowb = nowb; + flag_noopt = noopt; + flag_icells = icells; + flag_pwires = pwires; + flag_autowire = autowire; + use_internal_line_num(); +} + // internal dummy line number callbacks namespace { int internal_line_num; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 54b2fb319..93fee913e 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -299,6 +299,7 @@ namespace AST std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool mayfail); void reprocess_module(RTLIL::Design *design, dict local_interfaces) YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE; + void loadconfig() const; }; // this must be set by the language frontend before parsing the sources -- cgit v1.2.3 From c340fbfab23c582103402bbd812d9bca4510dc41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 23 Sep 2019 21:58:04 -0700 Subject: Force $inout.out ports to begin with '$' to indicate internal --- frontends/aiger/aigerparse.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e8ee487e5..986d34fb3 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -868,7 +868,7 @@ void AigerReader::post_process() if (!existing) { if (escaped_s.ends_with("$inout.out")) { wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(escaped_s.substr(0, escaped_s.size()-10)); + RTLIL::Wire *in_wire = module->wire(escaped_s.substr(1, escaped_s.size()-11)); log_assert(in_wire); log_assert(in_wire->port_input && !in_wire->port_output); in_wire->port_output = true; @@ -889,7 +889,7 @@ void AigerReader::post_process() if (!existing) { if (escaped_s.ends_with("$inout.out")) { wire->port_output = false; - RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(0, escaped_s.size()-10).c_str(), index)); + RTLIL::Wire *in_wire = module->wire(stringf("%s[%d]", escaped_s.substr(1, escaped_s.size()-11).c_str(), index)); log_assert(in_wire); log_assert(in_wire->port_input && !in_wire->port_output); in_wire->port_output = true; -- cgit v1.2.3 From 3f70c1fd26eb109c2c4d899cce55f24bbf04acc1 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 29 Sep 2019 13:22:11 +0200 Subject: Open aig frontend as binary file --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index e8ee487e5..b0a04749c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -1056,7 +1056,7 @@ struct AigerFrontend : public Frontend { } break; } - extra_args(f, filename, args, argidx); + extra_args(f, filename, args, argidx, true); if (module_name.empty()) { #ifdef _WIN32 -- cgit v1.2.3 From 9e55b234b47b01dc396e793b7f31236c9e87c185 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 29 Sep 2019 15:40:37 +0200 Subject: Fix reading aig files on windows --- frontends/aiger/aigerparse.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b0a04749c..ad35e9d76 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -285,6 +285,8 @@ end_of_header: } else if (c == 'c') { f.ignore(1); + if (f.peek() == '\r') + f.ignore(1); if (f.peek() == '\n') break; // Else constraint (TODO) @@ -1062,7 +1064,9 @@ struct AigerFrontend : public Frontend { #ifdef _WIN32 char fname[_MAX_FNAME]; _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */); - module_name = fname; + char* bn = strdup(fname); + module_name = RTLIL::escape_id(bn); + free(bn); #else char* bn = strdup(filename.c_str()); module_name = RTLIL::escape_id(bn); -- cgit v1.2.3 From 99a7f39084cf4b9cd21e2a1e4f4a842993dfd147 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 26 Sep 2019 03:57:16 +0000 Subject: rpc: new frontend. A new pass, connect_rpc, allows any HDL frontend that can read/write JSON from/to stdin/stdout or an unix socket or a named pipe to participate in elaboration as a first class citizen, such that any other HDL supported by Yosys directly or indirectly can transparently instantiate modules handled by this frontend. Recognizing that many HDL frontends emit Verilog, it allows the RPC frontend to direct Yosys to process the result of instantiation via any built-in Yosys frontend. The resulting RTLIL is then hygienically integrated into the overall design. --- frontends/rpc/Makefile.inc | 2 + frontends/rpc/rpc_frontend.cc | 589 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 591 insertions(+) create mode 100644 frontends/rpc/Makefile.inc create mode 100644 frontends/rpc/rpc_frontend.cc (limited to 'frontends') diff --git a/frontends/rpc/Makefile.inc b/frontends/rpc/Makefile.inc new file mode 100644 index 000000000..9af505098 --- /dev/null +++ b/frontends/rpc/Makefile.inc @@ -0,0 +1,2 @@ + +OBJS += frontends/rpc/rpc_frontend.o diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc new file mode 100644 index 000000000..b4b2fa3a2 --- /dev/null +++ b/frontends/rpc/rpc_frontend.cc @@ -0,0 +1,589 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2019 whitequark + * + * 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. + * + */ + +// The reason the -path mode of connect_rpc uses byte-oriented and not message-oriented sockets, even though +// it is a message-oriented interface, is that the system can place various limits on the message size, which +// are not always transparent or easy to change. Given that generated HDL code get be extremely large, it is +// unwise to rely on those limits being large enough, and using byte-oriented sockets is guaranteed to work. + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#endif + +#include "libs/json11/json11.hpp" +#include "libs/sha1/sha1.h" +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +#if defined(_WIN32) +static std::wstring str2wstr(const std::string &in) { + if(in == "") return L""; + std::wstring out; + out.resize(MultiByteToWideChar(/*CodePage=*/CP_UTF8, /*dwFlags=*/0, /*lpMultiByteStr=*/&in[0], /*cbMultiByte=*/(int)in.length(), /*lpWideCharStr=*/NULL, /*cchWideChar=*/0)); + int written = MultiByteToWideChar(/*CodePage=*/CP_UTF8, /*dwFlags=*/0, /*lpMultiByteStr=*/&in[0], /*cbMultiByte=*/(int)in.length(), /*lpWideCharStr=*/&out[0], /*cchWideChar=*/(int)out.length()); + log_assert(written == (int)out.length()); + return out; +} + +static std::string wstr2str(const std::wstring &in) { + if(in == L"") return ""; + std::string out; + out.resize(WideCharToMultiByte(/*CodePage=*/CP_UTF8, /*dwFlags=*/0, /*lpWideCharStr=*/&in[0], /*cchWideChar=*/(int)in.length(), /*lpMultiByteStr=*/NULL, /*cbMultiByte=*/0, /*lpDefaultChar=*/NULL, /*lpUsedDefaultChar=*/NULL)); + int written = WideCharToMultiByte(/*CodePage=*/CP_UTF8, /*dwFlags=*/0, /*lpWideCharStr=*/&in[0], /*cchWideChar=*/(int)in.length(), /*lpMultiByteStr=*/&out[0], /*cbMultiByte=*/(int)out.length(), /*lpDefaultChar=*/NULL, /*lpUsedDefaultChar=*/NULL); + log_assert(written == (int)out.length()); + return out; +} + +static std::string get_last_error_str() { + DWORD last_error = GetLastError(); + LPWSTR out_w; + DWORD size_w = FormatMessageW(/*dwFlags=*/FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS, /*lpSource=*/NULL, /*dwMessageId=*/last_error, /*dwLanguageId=*/0, /*lpBuffer=*/(LPWSTR)&out_w, /*nSize=*/0, /*Arguments=*/NULL); + if (size_w == 0) + return std::to_string(last_error); + std::string out = wstr2str(std::wstring(out_w, size_w)); + LocalFree(out_w); + return out; +} +#endif + +using json11::Json; + +struct RpcServer { + std::string name; + + RpcServer(const std::string &name) : name(name) { } + virtual ~RpcServer() { } + + virtual void write(const std::string &data) = 0; + virtual std::string read() = 0; + + Json call(const Json &json_request) { + std::string request; + json_request.dump(request); + request += '\n'; + log_debug("RPC frontend request: %s", request.c_str()); + write(request); + + std::string response = read(); + log_debug("RPC frontend response: %s", response.c_str()); + std::string error; + Json json_response = Json::parse(response, error); + if (json_response.is_null()) + log_cmd_error("parsing JSON failed: %s\n", error.c_str()); + if (json_response["error"].is_string()) + log_cmd_error("RPC frontend returned an error: %s\n", json_response["error"].string_value().c_str()); + return json_response; + } + + std::vector get_module_names() { + Json response = call(Json::object { + { "method", "modules" }, + }); + bool is_valid = true; + std::vector modules; + if (response["modules"].is_array()) { + for (auto &json_module : response["modules"].array_items()) { + if (json_module.is_string()) + modules.push_back(json_module.string_value()); + else is_valid = false; + } + } else is_valid = false; + if (!is_valid) + log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump().c_str()); + return modules; + } + + std::pair derive_module(const std::string &module, const dict ¶meters) { + Json::object json_parameters; + for (auto ¶m : parameters) { + std::string type, value; + if (param.second.flags & RTLIL::CONST_FLAG_REAL) { + type = "real"; + value = param.second.decode_string(); + } else if (param.second.flags & RTLIL::CONST_FLAG_STRING) { + type = "string"; + value = param.second.decode_string(); + } else if ((param.second.flags & ~RTLIL::CONST_FLAG_SIGNED) == RTLIL::CONST_FLAG_NONE) { + type = (param.second.flags & RTLIL::CONST_FLAG_SIGNED) ? "signed" : "unsigned"; + value = param.second.as_string(); + } else + log_cmd_error("Unserializable constant flags 0x%x\n", param.second.flags); + json_parameters[param.first.str()] = Json::object { + { "type", type }, + { "value", value }, + }; + } + Json response = call(Json::object { + { "method", "derive" }, + { "module", module }, + { "parameters", json_parameters }, + }); + bool is_valid = true; + std::string frontend, source; + if (response["frontend"].is_string()) + frontend = response["frontend"].string_value(); + else is_valid = false; + if (response["source"].is_string()) + source = response["source"].string_value(); + else is_valid = false; + if (!is_valid) + log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump().c_str()); + return std::make_pair(frontend, source); + } +}; + +struct RpcModule : RTLIL::Module { + std::shared_ptr server; + + RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool /*mayfail*/) YS_OVERRIDE { + std::string stripped_name = name.str(); + if (stripped_name.compare(0, 9, "$abstract") == 0) + stripped_name = stripped_name.substr(9); + log_assert(stripped_name[0] == '\\'); + + log_header(design, "Executing RPC frontend `%s' for module `%s'.\n", server->name.c_str(), stripped_name.c_str()); + + std::string parameter_info; + for (auto ¶m : parameters) { + log("Parameter %s = %s\n", param.first.c_str(), log_signal(RTLIL::SigSpec(param.second))); + parameter_info += stringf("%s=%s", param.first.c_str(), log_signal(RTLIL::SigSpec(param.second))); + } + + std::string derived_name; + if (parameters.empty()) + derived_name = stripped_name; + else if (parameter_info.size() > 60) + derived_name = "$paramod$" + sha1(parameter_info) + stripped_name; + else + derived_name = "$paramod" + stripped_name + parameter_info; + + if (design->has(derived_name)) { + log("Found cached RTLIL representation for module `%s'.\n", derived_name.c_str()); + } else { + std::string command, input; + std::tie(command, input) = server->derive_module(stripped_name.substr(1), parameters); + + std::istringstream input_stream(input); + RTLIL::Design *derived_design = new RTLIL::Design; + Frontend::frontend_call(derived_design, &input_stream, "" + derived_name.substr(8), command); + derived_design->check(); + + dict name_mangling; + bool found_derived_top = false; + for (auto module : derived_design->modules()) { + std::string original_name = module->name.str(); + if (original_name == stripped_name) { + found_derived_top = true; + name_mangling[original_name] = derived_name; + } else { + name_mangling[original_name] = derived_name + module->name.str(); + } + } + if (!found_derived_top) + log_cmd_error("RPC frontend did not return requested module `%s`!\n", stripped_name.c_str()); + + for (auto module : derived_design->modules()) + for (auto cell : module->cells()) + if (name_mangling.count(cell->type.str())) + cell->type = name_mangling[cell->type.str()]; + + for (auto module : derived_design->modules_) { + std::string mangled_name = name_mangling[module.first.str()]; + + log("Importing `%s' as `%s'.\n", log_id(module.first), log_id(mangled_name)); + + module.second->name = mangled_name; + module.second->design = design; + module.second->attributes.erase("\\top"); + design->modules_[mangled_name] = module.second; + derived_design->modules_.erase(module.first); + } + + delete derived_design; + } + + return derived_name; + } + + RTLIL::Module *clone() const YS_OVERRIDE { + RpcModule *new_mod = new RpcModule; + new_mod->server = server; + cloneInto(new_mod); + return new_mod; + } +}; + +#if defined(_WIN32) + +struct HandleRpcServer : RpcServer { + HANDLE hsend, hrecv; + + HandleRpcServer(const std::string &name, HANDLE hsend, HANDLE hrecv) + : RpcServer(name), hsend(hsend), hrecv(hrecv) { } + + void write(const std::string &data) YS_OVERRIDE { + log_assert(data.length() >= 1 && data.find('\n') == data.length() - 1); + ssize_t offset = 0; + do { + DWORD data_written; + if (!WriteFile(hsend, &data[offset], data.length() - offset, &data_written, /*lpOverlapped=*/NULL)) + log_cmd_error("WriteFile failed: %s\n", get_last_error_str().c_str()); + offset += data_written; + } while(offset < (ssize_t)data.length()); + } + + std::string read() YS_OVERRIDE { + std::string data; + ssize_t offset = 0; + while (data.length() == 0 || data[data.length() - 1] != '\n') { + data.resize(data.length() + 1024); + DWORD data_read; + if (!ReadFile(hrecv, &data[offset], data.length() - offset, &data_read, /*lpOverlapped=*/NULL)) + log_cmd_error("ReadFile failed: %s\n", get_last_error_str().c_str()); + offset += data_read; + data.resize(offset); + size_t term_pos = data.find('\n', offset); + if (term_pos != data.length() - 1 && term_pos != std::string::npos) + log_cmd_error("read failed: more than one response\n"); + } + return data; + } + + ~HandleRpcServer() { + CloseHandle(hsend); + if (hrecv != hsend) + CloseHandle(hrecv); + } +}; + +#else + +struct FdRpcServer : RpcServer { + int fdsend, fdrecv; + pid_t pid; + + FdRpcServer(const std::string &name, int fdsend, int fdrecv, pid_t pid = -1) + : RpcServer(name), fdsend(fdsend), fdrecv(fdrecv), pid(pid) { } + + void check_pid() { + if (pid == -1) return; + // If we're communicating with a process, check that it's still running, or we may get killed with SIGPIPE. + pid_t wait_result = ::waitpid(pid, NULL, WNOHANG); + if (wait_result == -1) + log_cmd_error("waitpid failed: %s\n", strerror(errno)); + if (wait_result == pid) + log_cmd_error("RPC frontend terminated unexpectedly\n"); + } + + void write(const std::string &data) YS_OVERRIDE { + log_assert(data.length() >= 1 && data.find('\n') == data.length() - 1); + ssize_t offset = 0; + do { + check_pid(); + ssize_t result = ::write(fdsend, &data[offset], data.length() - offset); + if (result == -1) + log_cmd_error("write failed: %s\n", strerror(errno)); + offset += result; + } while(offset < (ssize_t)data.length()); + } + + std::string read() YS_OVERRIDE { + std::string data; + ssize_t offset = 0; + while (data.length() == 0 || data[data.length() - 1] != '\n') { + data.resize(data.length() + 1024); + check_pid(); + ssize_t result = ::read(fdrecv, &data[offset], data.length() - offset); + if (result == -1) + log_cmd_error("read failed: %s\n", strerror(errno)); + offset += result; + data.resize(offset); + size_t term_pos = data.find('\n', offset); + if (term_pos != data.length() - 1 && term_pos != std::string::npos) + log_cmd_error("read failed: more than one response\n"); + } + return data; + } + + ~FdRpcServer() { + close(fdsend); + if (fdrecv != fdsend) + close(fdrecv); + } +}; + +#endif + +// RpcFrontend does not inherit from Frontend since it does not read files. +struct RpcFrontend : public Pass { + RpcFrontend() : Pass("connect_rpc", "connect to RPC frontend") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" connect_rpc -exec [args...]\n"); + log(" connect_rpc -path \n"); + log("\n"); + log("Load modules using an out-of-process frontend.\n"); + log("\n"); + log(" -exec [args...]\n"); + log(" run with arguments [args...]. send requests on stdin, read\n"); + log(" responses from stdout.\n"); + log("\n"); + log(" -path \n"); + log(" connect to Unix domain socket at . (Unix)\n"); + log(" connect to bidirectional byte-type named pipe at . (Windows)\n"); + log("\n"); + log("A simple JSON-based, newline-delimited protocol is used for communicating with\n"); + log("the frontend. Yosys requests data from the frontend by sending exactly 1 line\n"); + log("of JSON. Frontend responds with data or error message by replying with exactly\n"); + log("1 line of JSON as well.\n"); + log("\n"); + log(" -> {\"method\": \"modules\"}\n"); + log(" <- {\"modules\": [\"\", ...]}\n"); + log(" <- {\"error\": \"\"}\n"); + log(" request for the list of modules that can be derived by this frontend.\n"); + log(" the 'hierarchy' command will call back into this frontend if a cell\n"); + log(" with type is instantiated in the design.\n"); + log("\n"); + log(" -> {\"method\": \"derive\", \"module\": \", \"parameters\": {\n"); + log(" \"\": {\"type\": \"[unsigned|signed|string|real]\",\n"); + log(" \"value\": \"\"}, ...}}\n"); + log(" <- {\"frontend\": \"[ilang|verilog|...]\",\"source\": \"\"}}\n"); + log(" <- {\"error\": \"\"}\n"); + log(" request for the module to be derived for a specific set of\n"); + log(" parameters. starts with \\ for named parameters, and with $\n"); + log(" for unnamed parameters, which are numbered starting at 1.\n"); + log(" for integer parameters is always specified as a binary string of unlimited\n"); + log(" precision. the returned by the frontend is hygienically parsed\n"); + log(" by a built-in Yosys , allowing the RPC frontend to return any\n"); + log(" convenient representation of the module. the derived module is cached,\n"); + log(" so the response should be the same whenever the same set of parameters\n"); + log(" is provided.\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Connecting to RPC frontend.\n"); + + std::vector command; + std::string path; + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-exec" && argidx+1 < args.size()) { + command.insert(command.begin(), args.begin() + argidx + 1, args.end()); + continue; + } + if (arg == "-path" && argidx+1 < args.size()) { + path = args[argidx+1]; + continue; + } + break; + } + extra_args(args, argidx, design); + + if ((!command.empty()) + (!path.empty()) != 1) + log_cmd_error("Exactly one of -exec, -unix must be specified.\n"); + + std::shared_ptr server; + if (!command.empty()) { + std::string command_line; + bool first = true; + for (auto &arg : command) { + if (!first) command_line += ' '; + command_line += arg; + first = false; + } + +#ifdef _WIN32 + std::wstring command_w = str2wstr(command[0]); + std::wstring command_path_w; + std::wstring command_line_w = str2wstr(command_line); + DWORD command_path_len_w; + SECURITY_ATTRIBUTES pipe_attr = {}; + HANDLE send_r = NULL, send_w = NULL, recv_r = NULL, recv_w = NULL; + STARTUPINFOW startup_info = {}; + PROCESS_INFORMATION proc_info = {}; + + command_path_len_w = SearchPathW(/*lpPath=*/NULL, /*lpFileName=*/command_w.c_str(), /*lpExtension=*/L".exe", /*nBufferLength=*/0, /*lpBuffer=*/NULL, /*lpFilePart=*/NULL); + if (command_path_len_w == 0) { + log_error("SearchPathW failed: %s\n", get_last_error_str().c_str()); + goto cleanup_exec; + } + command_path_w.resize(command_path_len_w - 1); + command_path_len_w = SearchPathW(/*lpPath=*/NULL, /*lpFileName=*/command_w.c_str(), /*lpExtension=*/L".exe", /*nBufferLength=*/command_path_len_w, /*lpBuffer=*/&command_path_w[0], /*lpFilePart=*/NULL); + log_assert(command_path_len_w == command_path_w.length()); + + pipe_attr.nLength = sizeof(pipe_attr); + pipe_attr.bInheritHandle = TRUE; + pipe_attr.lpSecurityDescriptor = NULL; + if (!CreatePipe(&send_r, &send_w, &pipe_attr, /*nSize=*/0)) { + log_error("CreatePipe failed: %s\n", get_last_error_str().c_str()); + goto cleanup_exec; + } + if (!SetHandleInformation(send_w, HANDLE_FLAG_INHERIT, 0)) { + log_error("SetHandleInformation failed: %s\n", get_last_error_str().c_str()); + goto cleanup_exec; + } + if (!CreatePipe(&recv_r, &recv_w, &pipe_attr, /*nSize=*/0)) { + log_error("CreatePipe failed: %s\n", get_last_error_str().c_str()); + goto cleanup_exec; + } + if (!SetHandleInformation(recv_r, HANDLE_FLAG_INHERIT, 0)) { + log_error("SetHandleInformation failed: %s\n", get_last_error_str().c_str()); + goto cleanup_exec; + } + + startup_info.cb = sizeof(startup_info); + startup_info.hStdInput = send_r; + startup_info.hStdOutput = recv_w; + startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); + startup_info.dwFlags |= STARTF_USESTDHANDLES; + if (!CreateProcessW(/*lpApplicationName=*/command_path_w.c_str(), /*lpCommandLine=*/&command_line_w[0], /*lpProcessAttributes=*/NULL, /*lpThreadAttributes=*/NULL, /*bInheritHandles=*/TRUE, /*dwCreationFlags=*/0, /*lpEnvironment=*/NULL, /*lpCurrentDirectory=*/NULL, &startup_info, &proc_info)) { + log_error("CreateProcessW failed: %s\n", get_last_error_str().c_str()); + goto cleanup_exec; + } + CloseHandle(proc_info.hProcess); + CloseHandle(proc_info.hThread); + + server = std::make_shared(path, send_w, recv_r); + send_w = NULL; + recv_r = NULL; + +cleanup_exec: + if (send_r != NULL) CloseHandle(send_r); + if (send_w != NULL) CloseHandle(send_w); + if (recv_r != NULL) CloseHandle(recv_r); + if (recv_w != NULL) CloseHandle(recv_w); +#else + std::vector argv; + int send[2] = {-1,-1}, recv[2] = {-1,-1}; + posix_spawn_file_actions_t file_actions, *file_actions_p = NULL; + pid_t pid; + + for (auto &arg : command) + argv.push_back(&arg[0]); + argv.push_back(nullptr); + + if (pipe(send) != 0) { + log_error("pipe failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + if (pipe(recv) != 0) { + log_error("pipe failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + + if (posix_spawn_file_actions_init(&file_actions) != 0) { + log_error("posix_spawn_file_actions_init failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + file_actions_p = &file_actions; + if (posix_spawn_file_actions_adddup2(file_actions_p, send[0], STDIN_FILENO) != 0) { + log_error("posix_spawn_file_actions_adddup2 failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + if (posix_spawn_file_actions_addclose(file_actions_p, send[1]) != 0) { + log_error("posix_spawn_file_actions_addclose failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + if (posix_spawn_file_actions_adddup2(file_actions_p, recv[1], STDOUT_FILENO) != 0) { + log_error("posix_spawn_file_actions_adddup2 failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + if (posix_spawn_file_actions_addclose(file_actions_p, recv[0]) != 0) { + log_error("posix_spawn_file_actions_addclose failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + + if (posix_spawnp(&pid, argv[0], file_actions_p, /*attrp=*/NULL, argv.data(), environ) != 0) { + log_error("posix_spawnp failed: %s\n", strerror(errno)); + goto cleanup_exec; + } + + server = std::make_shared(command_line, send[1], recv[0], pid); + send[1] = -1; + recv[0] = -1; + +cleanup_exec: + if (send[0] != -1) close(send[0]); + if (send[1] != -1) close(send[1]); + if (recv[0] != -1) close(recv[0]); + if (recv[1] != -1) close(recv[1]); + if (file_actions_p != NULL) + posix_spawn_file_actions_destroy(file_actions_p); +#endif + } else if (!path.empty()) { +#ifdef _WIN32 + std::wstring path_w = str2wstr(path); + HANDLE h; + + h = CreateFileW(path_w.c_str(), GENERIC_READ|GENERIC_WRITE, /*dwShareMode=*/0, /*lpSecurityAttributes=*/NULL, /*dwCreationDisposition=*/OPEN_EXISTING, /*dwFlagsAndAttributes=*/0, /*hTemplateFile=*/NULL); + if (h == INVALID_HANDLE_VALUE) { + log_error("CreateFileW failed: %s\n", get_last_error_str().c_str()); + goto cleanup_path; + } + + server = std::make_shared(path, h, h); + +cleanup_path: + ; +#else + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1); + + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + log_error("socket failed: %s\n", strerror(errno)); + goto cleanup_path; + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { + log_error("connect failed: %s\n", strerror(errno)); + goto cleanup_path; + } + + server = std::make_shared(path, fd, fd); + fd = -1; + +cleanup_path: + if (fd != -1) close(fd); +#endif + } + + if (!server) + log_cmd_error("Failed to connect to RPC frontend.\n"); + + for (auto &module_name : server->get_module_names()) { + log("Linking module `%s'.\n", module_name.c_str()); + RpcModule *module = new RpcModule; + module->name = "$abstract\\" + module_name; + module->server = server; + design->add(module); + } + } +} RpcFrontend; + +YOSYS_NAMESPACE_END -- cgit v1.2.3 From 08b55a20e36a24d09be9016ceda658bc8ba04ad3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 14:11:01 -0700 Subject: module->derive() to be lazy and not touch ast if already derived --- frontends/ast/ast.cc | 82 ++++++++++++++++++++++++++++++++-------------------- frontends/ast/ast.h | 2 +- 2 files changed, 51 insertions(+), 33 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 21279cbfa..e4539f303 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1382,10 +1382,10 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool /*mayfail*/) { AstNode *new_ast = NULL; - std::string modname = derive_common(design, parameters, &new_ast, mayfail); + std::string modname = derive_common(design, parameters, &new_ast); // Since interfaces themselves may be instantiated with different parameters, // "modname" must also take those into account, so that unique modules @@ -1455,10 +1455,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, bool mayfail) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, bool /*mayfail*/) { AstNode *new_ast = NULL; - std::string modname = derive_common(design, parameters, &new_ast, mayfail); + std::string modname = derive_common(design, parameters, &new_ast); if (!design->has(modname)) { new_ast->str = modname; @@ -1473,47 +1473,75 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool) +std::string AstModule::derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out) { std::string stripped_name = name.str(); if (stripped_name.compare(0, 9, "$abstract") == 0) stripped_name = stripped_name.substr(9); - log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str()); - loadconfig(); - std::string para_info; - AstNode *new_ast = ast->clone(); int para_counter = 0; - int orig_parameters_n = parameters.size(); - for (auto it = new_ast->children.begin(); it != new_ast->children.end(); it++) { - AstNode *child = *it; + for (const auto child : ast->children) { if (child->type != AST_PARAMETER) continue; para_counter++; std::string para_id = child->str; if (parameters.count(para_id) > 0) { log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str]))); - rewrite_parameter: para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); - delete child->children.at(0); - if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) { - child->children[0] = new AstNode(AST_REALVALUE); - child->children[0]->realvalue = std::stod(parameters[para_id].decode_string()); - } else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0) - child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string()); - else - child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0); - parameters.erase(para_id); continue; } para_id = stringf("$%d", para_counter); + if (parameters.count(para_id) > 0) { + log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); + para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); + continue; + } + } + + std::string modname; + if (parameters.size() == 0) + modname = stripped_name; + else if (para_info.size() > 60) + modname = "$paramod$" + sha1(para_info) + stripped_name; + else + modname = "$paramod" + stripped_name + para_info; + + if (design->has(modname)) + return modname; + + log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str()); + loadconfig(); + + AstNode *new_ast = ast->clone(); + para_counter = 0; + for (auto child : new_ast->children) { + if (child->type != AST_PARAMETER) + continue; + para_counter++; + std::string para_id = child->str; + if (parameters.count(para_id) > 0) { + log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str]))); + goto rewrite_parameter; + } + para_id = stringf("$%d", para_counter); if (parameters.count(para_id) > 0) { log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id]))); goto rewrite_parameter; } + continue; + rewrite_parameter: + delete child->children.at(0); + if ((parameters[para_id].flags & RTLIL::CONST_FLAG_REAL) != 0) { + child->children[0] = new AstNode(AST_REALVALUE); + child->children[0]->realvalue = std::stod(parameters[para_id].decode_string()); + } else if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0) + child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string()); + else + child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0); + parameters.erase(para_id); } for (auto param : parameters) { @@ -1526,16 +1554,6 @@ std::string AstModule::derive_common(RTLIL::Design *design, dictchildren.push_back(defparam); } - std::string modname; - - if (orig_parameters_n == 0) - modname = stripped_name; - else if (para_info.size() > 60) - modname = "$paramod$" + sha1(para_info) + stripped_name; - else - modname = "$paramod" + stripped_name + para_info; - - (*new_ast_out) = new_ast; return modname; } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 93fee913e..0ec249ab9 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -296,7 +296,7 @@ namespace AST ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, bool mayfail) YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict parameters, dict interfaces, dict modports, bool mayfail) YS_OVERRIDE; - std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out, bool mayfail); + std::string derive_common(RTLIL::Design *design, dict parameters, AstNode **new_ast_out); void reprocess_module(RTLIL::Design *design, dict local_interfaces) YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE; void loadconfig() const; -- cgit v1.2.3 From 0a1af434e8acfaa692d7990bce68fd23daed9519 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Sep 2019 14:52:04 -0700 Subject: Fix for svinterfaces --- frontends/ast/ast.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index e4539f303..37a69d8bf 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1398,11 +1398,17 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dicthas(modname)) { + if (!design->has(new_modname)) { + if (!new_ast) { + auto mod = dynamic_cast(design->module(modname)); + new_ast = mod->ast->clone(); + } + modname = new_modname; new_ast->str = modname; // Iterate over all interfaces which are ports in this module: -- cgit v1.2.3 From c026579c207b81092e298858acf131c70115f89f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 1 Oct 2019 18:45:07 +0200 Subject: Define environ, fixes #1424 --- frontends/rpc/rpc_frontend.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'frontends') diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index b4b2fa3a2..83e1353b0 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -34,6 +34,8 @@ #include "libs/sha1/sha1.h" #include "kernel/yosys.h" +extern char **environ; + YOSYS_NAMESPACE_BEGIN #if defined(_WIN32) -- cgit v1.2.3 From f6b5e47e40b4a2bda6e5d928480ea218a6a911c2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Sep 2019 20:43:13 +0100 Subject: sv: Switch parser to glr, prep for typedef Signed-off-by: David Shah --- frontends/ast/ast.cc | 3 +++ frontends/ast/ast.h | 7 ++++-- frontends/ast/genrtlil.cc | 1 + frontends/ast/simplify.cc | 51 ++++++++++++++++++++++++++++++++++---- frontends/verilog/verilog_parser.y | 38 +++++++++++++++++++++++++--- 5 files changed, 89 insertions(+), 11 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 21279cbfa..937dad9be 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -164,6 +164,8 @@ std::string AST::type2str(AstNodeType type) X(AST_MODPORT) X(AST_MODPORTMEMBER) X(AST_PACKAGE) + X(AST_WIRETYPE) + X(AST_TYPEDEF) #undef X default: log_abort(); @@ -206,6 +208,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch was_checked = false; range_valid = false; range_swapped = false; + is_custom_type = false; port_id = 0; range_left = -1; range_right = 0; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 93fee913e..fcc661b4c 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -148,7 +148,10 @@ namespace AST AST_INTERFACEPORTTYPE, AST_MODPORT, AST_MODPORTMEMBER, - AST_PACKAGE + AST_PACKAGE, + + AST_WIRETYPE, + AST_TYPEDEF }; // convert an node type to a string (e.g. for debug output) @@ -174,7 +177,7 @@ namespace AST // node content - most of it is unused in most node types std::string str; std::vector bits; - bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized; + bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type; int port_id, range_left, range_right; uint32_t integer; double realvalue; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 407a34472..94f5c0a04 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -863,6 +863,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_PACKAGE: case AST_MODPORT: case AST_MODPORTMEMBER: + case AST_TYPEDEF: break; case AST_INTERFACEPORT: { // If a port in a module with unknown type is found, mark it with the attribute 'is_interface' diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index b1ee22f42..b94662bcd 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -318,7 +318,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.) - if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) + if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF) const_fold = true; if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) const_fold = true; @@ -336,6 +336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, std::map this_wire_scope; for (size_t i = 0; i < children.size(); i++) { AstNode *node = children[i]; + if (node->type == AST_WIRE) { if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { for (auto c : node->children[0]->children) { @@ -405,14 +406,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, this_wire_scope[node->str] = node; } if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || - node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) { + node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL || + node->type == AST_TYPEDEF) { backup_scope[node->str] = current_scope[node->str]; current_scope[node->str] = node; } } for (size_t i = 0; i < children.size(); i++) { AstNode *node = children[i]; - if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY) + if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF) while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM)) did_something = true; } @@ -780,6 +782,44 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, delete_children(); } + // resolve typedefs + if (type == AST_TYPEDEF) { + log_assert(children.size() == 1); + log_assert(children[0]->type == AST_WIRE); + while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + log_assert(!children[0]->is_custom_type); + } + + // resolve types of wires and parameters + if (type == AST_WIRE || type == AST_LOCALPARAM || type == AST_PARAMETER) { + if (is_custom_type) { + log_assert(children.size() == 1); + log_assert(children[0]->type == AST_WIRETYPE); + if (!current_scope.count(children[0]->str)) + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name", children[0]->str.c_str()); + AstNode *resolved_type = current_scope.at(children[0]->str); + if (resolved_type->type != AST_TYPEDEF) + log_file_error(filename, linenum, "`%s' does not name a type", children[0]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; + delete_children(); // type reference no longer needed + + is_reg = templ->is_reg; + is_logic = templ->is_logic; + is_signed = templ->is_signed; + is_string = templ->is_string; + is_custom_type = templ->is_custom_type; + + range_valid = templ->range_valid; + range_swapped = templ->range_swapped; + range_left = templ->range_left; + range_right = templ->range_right; + for (auto template_child : templ->children) + children.push_back(template_child->clone()); + } + log_assert(!is_custom_type); + } + // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { @@ -1194,7 +1234,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_BLOCK && str.empty()) { for (size_t i = 0; i < children.size(); i++) - if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) + if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n"); } @@ -1206,7 +1246,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, std::vector new_children; for (size_t i = 0; i < children.size(); i++) - if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) { + if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) { children[i]->simplify(false, false, false, stage, -1, false, false); current_ast_mod->children.push_back(children[i]); current_scope[children[i]->str] = children[i]; @@ -2945,6 +2985,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma child->expand_genblock(index_var, prefix, name_map); } + if (backup_name_map.size() > 0) name_map.swap(backup_name_map); } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4afd72b73..eb091bea6 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -112,6 +112,8 @@ struct specify_rise_fall { %define api.prefix {frontend_verilog_yy} +%glr-parser + /* The union is defined in the header, so we need to provide all the * includes it requires */ @@ -180,7 +182,7 @@ struct specify_rise_fall { %right UNARY_OPS %define parse.error verbose -%define parse.lac full +// %define parse.lac full %nonassoc FAKE_THEN %nonassoc TOK_ELSE @@ -206,6 +208,7 @@ design: task_func_decl design | param_decl design | localparam_decl design | + typedef_decl design | package design | interface design | /* empty */; @@ -426,6 +429,7 @@ package_body: package_body package_body_stmt |; package_body_stmt: + typedef_decl | localparam_decl; interface: @@ -452,7 +456,7 @@ interface_body: interface_body interface_body_stmt |; interface_body_stmt: - param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | + param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | modport_stmt; non_opt_delay: @@ -529,6 +533,11 @@ wire_type_token: } | TOK_CONST { current_wire_const = true; + } | + hierarchical_id { + astbuf3->is_custom_type = true; + astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); + astbuf3->children.back()->str = *$1; }; non_opt_range: @@ -591,7 +600,7 @@ module_body: /* empty */; module_body_stmt: - task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | + task_func_decl | specify_block |param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; checker_decl: @@ -1377,6 +1386,27 @@ assign_expr: ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); }; +typedef_decl: + TOK_TYPEDEF wire_type range TOK_ID ';' { + astbuf1 = $2; + astbuf2 = $3; + if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { + if (astbuf2) { + frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); + } else { + astbuf2 = new AstNode(AST_RANGE); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); + astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); + } + } + if (astbuf2 && astbuf2->children.size() != 2) + frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); + if (astbuf2) + astbuf1->children.push_back(astbuf2); + ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); + ast_stack.back()->children.back()->str = *$4; + }; + cell_stmt: attr TOK_ID { astbuf1 = new AstNode(AST_CELL); @@ -1823,7 +1853,7 @@ simple_behavioral_stmt: // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: - defattr | assert | wire_decl | param_decl | localparam_decl | + defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | non_opt_delay behavioral_stmt | simple_behavioral_stmt ';' | ';' | hierarchical_id attr { -- cgit v1.2.3 From c9629516120930aedaf52d72fec5d7fabe51d496 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Sep 2019 21:07:20 +0100 Subject: sv: Fix typedef parameters Signed-off-by: David Shah --- frontends/ast/simplify.cc | 33 +++++++++++++++++++++++++++++++-- frontends/verilog/verilog_parser.y | 21 +++++++++++++++++---- 2 files changed, 48 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index b94662bcd..9abd2916d 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -790,8 +790,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_assert(!children[0]->is_custom_type); } - // resolve types of wires and parameters - if (type == AST_WIRE || type == AST_LOCALPARAM || type == AST_PARAMETER) { + // resolve types of wires + if (type == AST_WIRE) { if (is_custom_type) { log_assert(children.size() == 1); log_assert(children[0]->type == AST_WIRETYPE); @@ -820,6 +820,35 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_assert(!is_custom_type); } + // resolve types of parameters + if (type == AST_LOCALPARAM || type == AST_PARAMETER) { + if (is_custom_type) { + log_assert(children.size() == 2); + log_assert(children[1]->type == AST_WIRETYPE); + if (!current_scope.count(children[1]->str)) + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name", children[1]->str.c_str()); + AstNode *resolved_type = current_scope.at(children[1]->str); + if (resolved_type->type != AST_TYPEDEF) + log_file_error(filename, linenum, "`%s' does not name a type", children[1]->str.c_str()); + log_assert(resolved_type->children.size() == 1); + AstNode *templ = resolved_type->children[0]; + delete children[1]; + children.pop_back(); + + is_signed = templ->is_signed; + is_string = templ->is_string; + is_custom_type = templ->is_custom_type; + + range_valid = templ->range_valid; + range_swapped = templ->range_swapped; + range_left = templ->range_left; + range_right = templ->range_right; + for (auto template_child : templ->children) + children.push_back(template_child->clone()); + } + log_assert(!is_custom_type); + } + // resolve constant prefixes if (type == AST_PREFIX) { if (children[0]->type != AST_CONSTANT) { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index eb091bea6..8cc084fe0 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -327,13 +327,13 @@ single_module_para: astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_range single_param_decl | + } int_param_type single_param_decl | attr TOK_LOCALPARAM { if (astbuf1) delete astbuf1; astbuf1 = new AstNode(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_range single_param_decl | + } int_param_type single_param_decl | single_param_decl; module_args_opt: @@ -1158,12 +1158,25 @@ param_range: } }; +custom_param_type: + hierarchical_id { + astbuf1->is_custom_type = true; + astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); + astbuf1->children.back()->str = *$1; + }; + +param_type: + param_signed param_integer param_real param_range | custom_param_type; + +int_param_type: + param_signed param_integer param_range | custom_param_type; + param_decl: attr TOK_PARAMETER { astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_real param_range param_decl_list ';' { + } param_type param_decl_list ';' { delete astbuf1; }; @@ -1172,7 +1185,7 @@ localparam_decl: astbuf1 = new AstNode(AST_LOCALPARAM); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); append_attr(astbuf1, $1); - } param_signed param_integer param_real param_range param_decl_list ';' { + } param_type param_decl_list ';' { delete astbuf1; }; -- cgit v1.2.3 From e70e4afb60a41da6d9f6200b20f36f61c6b993b2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 19 Sep 2019 21:21:21 +0100 Subject: sv: Fix typedefs in packages Signed-off-by: David Shah --- frontends/ast/simplify.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9abd2916d..44e32b29c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -796,14 +796,17 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_assert(children.size() == 1); log_assert(children[0]->type == AST_WIRETYPE); if (!current_scope.count(children[0]->str)) - log_file_error(filename, linenum, "Unknown identifier `%s' used as type name", children[0]->str.c_str()); + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str()); AstNode *resolved_type = current_scope.at(children[0]->str); if (resolved_type->type != AST_TYPEDEF) - log_file_error(filename, linenum, "`%s' does not name a type", children[0]->str.c_str()); + log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str()); log_assert(resolved_type->children.size() == 1); AstNode *templ = resolved_type->children[0]; delete_children(); // type reference no longer needed + // Ensure typedef itself is fully simplified + while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + is_reg = templ->is_reg; is_logic = templ->is_logic; is_signed = templ->is_signed; @@ -826,15 +829,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_assert(children.size() == 2); log_assert(children[1]->type == AST_WIRETYPE); if (!current_scope.count(children[1]->str)) - log_file_error(filename, linenum, "Unknown identifier `%s' used as type name", children[1]->str.c_str()); + log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); AstNode *resolved_type = current_scope.at(children[1]->str); if (resolved_type->type != AST_TYPEDEF) - log_file_error(filename, linenum, "`%s' does not name a type", children[1]->str.c_str()); + log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str()); log_assert(resolved_type->children.size() == 1); AstNode *templ = resolved_type->children[0]; delete children[1]; children.pop_back(); + // Ensure typedef itself is fully simplified + while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + is_signed = templ->is_signed; is_string = templ->is_string; is_custom_type = templ->is_custom_type; -- cgit v1.2.3 From 30d23260309ef392a0e69fe5294c38b71ad0692e Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 11:39:15 +0100 Subject: sv: Add support for memory typedefs Signed-off-by: David Shah --- frontends/ast/simplify.cc | 17 +++++++++++++++-- frontends/verilog/verilog_parser.y | 20 +++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 44e32b29c..a6ac04037 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -785,8 +785,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // resolve typedefs if (type == AST_TYPEDEF) { log_assert(children.size() == 1); - log_assert(children[0]->type == AST_WIRE); - while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY); + while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { + did_something = true; + }; log_assert(!children[0]->is_custom_type); } @@ -807,6 +809,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // Ensure typedef itself is fully simplified while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + type = templ->type; is_reg = templ->is_reg; is_logic = templ->is_logic; is_signed = templ->is_signed; @@ -819,6 +822,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, range_right = templ->range_right; for (auto template_child : templ->children) children.push_back(template_child->clone()); + did_something = true; } log_assert(!is_custom_type); } @@ -841,6 +845,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // Ensure typedef itself is fully simplified while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + if (templ->type == AST_MEMORY) + log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); is_signed = templ->is_signed; is_string = templ->is_string; is_custom_type = templ->is_custom_type; @@ -851,6 +857,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, range_right = templ->range_right; for (auto template_child : templ->children) children.push_back(template_child->clone()); + did_something = true; } log_assert(!is_custom_type); } @@ -3074,6 +3081,9 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg uint32_t children_flags = 0; int lhs_children_counter = 0; + if (type == AST_TYPEDEF) + return; // don't touch content of typedefs + if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) { // mark all memories that are used in a complex expression on the left side of an assignment @@ -3231,6 +3241,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool &mem2reg_set, AstNode *mod, if (type == AST_FUNCTION || type == AST_TASK) return false; + if (type == AST_TYPEDEF) + return false; + if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) { log_assert(children[0]->type == AST_CONSTANT); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8cc084fe0..ba44d7f3d 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1400,7 +1400,7 @@ assign_expr: }; typedef_decl: - TOK_TYPEDEF wire_type range TOK_ID ';' { + TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { astbuf1 = $2; astbuf2 = $3; if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { @@ -1416,6 +1416,24 @@ typedef_decl: frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [:], [+:], or [-:]"); if (astbuf2) astbuf1->children.push_back(astbuf2); + + if ($5 != NULL) { + if (!astbuf2) { + AstNode *rng = new AstNode(AST_RANGE); + rng->children.push_back(AstNode::mkconst_int(0, true)); + rng->children.push_back(AstNode::mkconst_int(0, true)); + astbuf1->children.push_back(rng); + } + astbuf1->type = AST_MEMORY; + auto *rangeNode = $5; + if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { + // SV array size [n], rewrite as [n-1:0] + rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); + rangeNode->children.push_back(AstNode::mkconst_int(0, false)); + } + astbuf1->children.push_back(rangeNode); + } + ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); ast_stack.back()->children.back()->str = *$4; }; -- cgit v1.2.3 From af25585170f87506bcc7dbe5afe0fec868290d5b Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 11:46:37 +0100 Subject: sv: Add support for memories of a typedef Signed-off-by: David Shah --- frontends/ast/simplify.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index a6ac04037..aaf1188b4 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -793,9 +793,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } // resolve types of wires - if (type == AST_WIRE) { + if (type == AST_WIRE || type == AST_MEMORY) { if (is_custom_type) { - log_assert(children.size() == 1); + log_assert(children.size() >= 1); log_assert(children[0]->type == AST_WIRETYPE); if (!current_scope.count(children[0]->str)) log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str()); @@ -804,12 +804,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str()); log_assert(resolved_type->children.size() == 1); AstNode *templ = resolved_type->children[0]; - delete_children(); // type reference no longer needed + // Remove type reference + delete children[0]; + children.erase(children.begin()); // Ensure typedef itself is fully simplified while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; - type = templ->type; + if (type == AST_WIRE) + type = templ->type; is_reg = templ->is_reg; is_logic = templ->is_logic; is_signed = templ->is_signed; @@ -820,8 +823,19 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, range_swapped = templ->range_swapped; range_left = templ->range_left; range_right = templ->range_right; - for (auto template_child : templ->children) - children.push_back(template_child->clone()); + + // Insert clones children from template at beginning + for (int i = 0; i < GetSize(templ->children); i++) + children.insert(children.begin() + i, templ->children[i]->clone()); + + if (type == AST_MEMORY && GetSize(children) == 1) { + // Single-bit memories must have [0:0] range + AstNode *rng = new AstNode(AST_RANGE); + rng->children.push_back(AstNode::mkconst_int(0, true)); + rng->children.push_back(AstNode::mkconst_int(0, true)); + children.insert(children.begin(), rng); + } + did_something = true; } log_assert(!is_custom_type); -- cgit v1.2.3 From 497faf4ec0c078093ecef547965ae9d0fd153edb Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 11:59:33 +0100 Subject: sv: Add %expect Signed-off-by: David Shah --- frontends/verilog/verilog_parser.y | 1 + 1 file changed, 1 insertion(+) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ba44d7f3d..e0a654b76 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -113,6 +113,7 @@ struct specify_rise_fall { %define api.prefix {frontend_verilog_yy} %glr-parser +%expect 22 /* The union is defined in the header, so we need to provide all the * includes it requires -- cgit v1.2.3 From c0bb47beca2fb78670ab14515047a88a677cc608 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 12:11:17 +0100 Subject: sv: Fix memories of typedefs Signed-off-by: David Shah --- frontends/verilog/verilog_parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index e0a654b76..516fa4138 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1350,7 +1350,7 @@ wire_name: if ($2 != NULL) { if (node->is_input || node->is_output) frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); - if (!astbuf2) { + if (!astbuf2 && !node->is_custom_type) { AstNode *rng = new AstNode(AST_RANGE); rng->children.push_back(AstNode::mkconst_int(0, true)); rng->children.push_back(AstNode::mkconst_int(0, true)); -- cgit v1.2.3 From 8cc1bee33c04690d729d1a8b8622be05d65f7911 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 16:12:09 +0100 Subject: sv: Disambiguate interface ports Signed-off-by: David Shah --- frontends/verilog/verilog_parser.y | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'frontends') diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 516fa4138..0024d4778 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -113,7 +113,8 @@ struct specify_rise_fall { %define api.prefix {frontend_verilog_yy} %glr-parser -%expect 22 +%expect 21 +%expect-rr 2 /* The union is defined in the header, so we need to provide all the * includes it requires @@ -157,7 +158,7 @@ struct specify_rise_fall { %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %type range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list +%type wire_type wire_type_io expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id %type opt_signed opt_property unique_case_attr %type attr case_attr @@ -395,7 +396,7 @@ module_arg: ast_stack.back()->children.push_back(astbuf2); delete astbuf1; // really only needed if multiple instances of same type. } module_arg_opt_assignment | - attr wire_type range TOK_ID { + attr wire_type_io range TOK_ID { AstNode *node = $2; node->str = *$4; node->port_id = ++port_counter; @@ -479,6 +480,15 @@ wire_type: $$ = astbuf3; }; +wire_type_io: + { + astbuf3 = new AstNode(AST_WIRE); + current_wire_rand = false; + current_wire_const = false; + } io_wire_type_token_list delay { + $$ = astbuf3; + }; + wire_type_token_list: wire_type_token | wire_type_token_list wire_type_token | wire_type_token_io ; @@ -541,6 +551,12 @@ wire_type_token: astbuf3->children.back()->str = *$1; }; +wire_type_token_list_without_io: + wire_type_token | wire_type_token_list wire_type_token; + +io_wire_type_token_list: + wire_type_token_io | wire_type_token_io wire_type_token_list_without_io; + non_opt_range: '[' expr ':' expr ']' { $$ = new AstNode(AST_RANGE); -- cgit v1.2.3 From 5501d9090aaf2d508b2f082f8453effe7fce08df Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 20 Sep 2019 18:40:23 +0100 Subject: sv: Fix typedefs in blocks Signed-off-by: David Shah --- frontends/ast/simplify.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index aaf1188b4..0ebc183b2 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3002,7 +3002,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma } } - if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) + if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0) str = name_map[str]; std::map backup_name_map; @@ -3010,7 +3010,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma for (size_t i = 0; i < children.size(); i++) { AstNode *child = children[i]; if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || - child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) { + child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) { if (backup_name_map.size() == 0) backup_name_map = name_map; std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix; -- cgit v1.2.3 From e46e8753c84ee83f871d5ce116ce4c08dd49a031 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 3 Oct 2019 09:55:43 +0100 Subject: frontends/ast: code style Signed-off-by: David Shah --- frontends/ast/simplify.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 0ebc183b2..44fd32cdc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -786,9 +786,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (type == AST_TYPEDEF) { log_assert(children.size() == 1); log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY); - while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { + while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) did_something = true; - }; log_assert(!children[0]->is_custom_type); } -- cgit v1.2.3 From c0b14cfea7c5650ddbc28d69de4749f845954dc7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 4 Oct 2019 16:29:46 +0200 Subject: Fixes for MSVC build --- frontends/rpc/rpc_frontend.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'frontends') diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index 83e1353b0..add17c243 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -28,14 +28,13 @@ #include #include #include +extern char **environ; #endif #include "libs/json11/json11.hpp" #include "libs/sha1/sha1.h" #include "kernel/yosys.h" -extern char **environ; - YOSYS_NAMESPACE_BEGIN #if defined(_WIN32) @@ -238,6 +237,11 @@ struct RpcModule : RTLIL::Module { #if defined(_WIN32) +#if defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + struct HandleRpcServer : RpcServer { HANDLE hsend, hrecv; -- cgit v1.2.3 From aae2b9fd9c8dc915fadacc24962436dd7aedff36 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 4 Oct 2019 11:04:10 -0700 Subject: Rename abc_* names/attributes to more precisely be abc9_* --- frontends/aiger/aigerparse.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'frontends') diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 5a1da4db1..cf060193d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -740,22 +740,22 @@ void AigerReader::post_process() log_assert(box_module); if (seen_boxes.insert(cell->type).second) { - auto it = box_module->attributes.find("\\abc_carry"); + auto it = box_module->attributes.find("\\abc9_carry"); if (it != box_module->attributes.end()) { RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; auto carry_in_out = it->second.decode_string(); auto pos = carry_in_out.find(','); if (pos == std::string::npos) - log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); + log_error("'abc9_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); carry_in = box_module->wire(carry_in_name); if (!carry_in || !carry_in->port_input) - log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); + log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); carry_out = box_module->wire(carry_out_name); if (!carry_out || !carry_out->port_output) - log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); + log_error("'abc9_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); auto &ports = box_module->ports; for (auto jt = ports.begin(); jt != ports.end(); ) { -- cgit v1.2.3 From 935d3e19e2ddc315d06b4a7fe649f06578eeeb81 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 16 Oct 2019 00:00:27 +0200 Subject: Add .blackbox support to blif front-end Signed-off-by: Clifford Wolf --- frontends/blif/blifparse.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'frontends') diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index d17cacf29..bfcfad78a 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -174,6 +174,12 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (module == nullptr) goto error; + if (!strcmp(cmd, ".blackbox")) + { + module->attributes["\\blackbox"] = RTLIL::Const(1); + continue; + } + if (!strcmp(cmd, ".end")) { for (auto &wp : wideports_cache) -- cgit v1.2.3 From 71936209cf194c06dc59d5e17bf3c153a000892f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 16 Oct 2019 09:06:57 +0200 Subject: Fix parsing of .cname BLIF statements Signed-off-by: Clifford Wolf --- frontends/blif/blifparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'frontends') diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index bfcfad78a..cab210605 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -286,7 +286,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool goto error_with_reason; } - module->rename(lastcell, p); + module->rename(lastcell, RTLIL::escape_id(p)); continue; } -- cgit v1.2.3