aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/aiger/aigerparse.cc746
-rw-r--r--frontends/aiger/aigerparse.h10
-rw-r--r--frontends/ast/ast.cc27
-rw-r--r--frontends/ast/genrtlil.cc3
-rw-r--r--frontends/ast/simplify.cc30
-rw-r--r--frontends/blif/blifparse.cc2
-rw-r--r--frontends/blif/blifparse.h2
-rw-r--r--frontends/ilang/ilang_parser.y13
-rw-r--r--frontends/json/jsonparse.cc81
-rw-r--r--frontends/liberty/liberty.cc2
-rw-r--r--frontends/verific/verific.cc72
-rw-r--r--frontends/verific/verific.h4
-rw-r--r--frontends/verific/verificsva.cc2
-rw-r--r--frontends/verilog/const2ast.cc38
-rw-r--r--frontends/verilog/verilog_lexer.l5
-rw-r--r--frontends/verilog/verilog_parser.y112
16 files changed, 904 insertions, 245 deletions
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 68552fd06..06522939f 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -2,7 +2,7 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Eddie Hung <eddie@fpgeh.com>
+ * 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -22,19 +22,191 @@
// Armin Biere. The AIGER And-Inverter Graph (AIG) Format Version 20071012. Technical Report 07/1, October 2011, FMV Reports Series, Institute for Formal Models and Verification, Johannes Kepler University, Altenbergerstr. 69, 4040 Linz, Austria.
// http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf
-#ifndef _WIN32
-#include <libgen.h>
+// https://stackoverflow.com/a/46137633
+#ifdef _MSC_VER
+#include <stdlib.h>
+#define __builtin_bswap32 _byteswap_ulong
+#elif defined(__APPLE__)
+#include <libkern/OSByteOrder.h>
+#define __builtin_bswap32 OSSwapInt32
#endif
-#include <array>
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
#include "aigerparse.h"
YOSYS_NAMESPACE_BEGIN
-AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name)
- : design(design), f(f), clk_name(clk_name)
+inline int32_t from_big_endian(int32_t i32) {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ return __builtin_bswap32(i32);
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ return i32;
+#else
+#error "Unknown endianness"
+#endif
+}
+
+#define log_debug2(...) ;
+//#define log_debug2(...) log_debug(__VA_ARGS__)
+
+struct ConstEvalAig
+{
+ RTLIL::Module *module;
+ dict<RTLIL::SigBit, RTLIL::State> values_map;
+ dict<RTLIL::SigBit, RTLIL::Cell*> sig2driver;
+ dict<SigBit, pool<RTLIL::SigBit>> sig2deps;
+
+ ConstEvalAig(RTLIL::Module *module) : module(module)
+ {
+ for (auto &it : module->cells_) {
+ if (!yosys_celltypes.cell_known(it.second->type))
+ continue;
+ for (auto &it2 : it.second->connections())
+ if (yosys_celltypes.cell_output(it.second->type, it2.first)) {
+ auto r YS_ATTRIBUTE(unused) = sig2driver.insert(std::make_pair(it2.second, it.second));
+ log_assert(r.second);
+ }
+ }
+ }
+
+ void clear()
+ {
+ values_map.clear();
+ sig2deps.clear();
+ }
+
+ void set(RTLIL::SigBit sig, RTLIL::State value)
+ {
+ auto it = values_map.find(sig);
+#ifndef NDEBUG
+ if (it != values_map.end()) {
+ RTLIL::State current_val = it->second;
+ log_assert(current_val == value);
+ }
+#endif
+ if (it != values_map.end())
+ it->second = value;
+ else
+ values_map[sig] = value;
+ }
+
+ void set_incremental(RTLIL::SigSpec sig, RTLIL::Const value)
+ {
+ log_assert(GetSize(sig) == GetSize(value));
+
+ for (int i = 0; i < GetSize(sig); i++) {
+ auto it = values_map.find(sig[i]);
+ if (it != values_map.end()) {
+ RTLIL::State current_val = it->second;
+ if (current_val != value[i])
+ for (auto dep : sig2deps[sig[i]])
+ values_map.erase(dep);
+ it->second = value[i];
+ }
+ else
+ values_map[sig[i]] = value[i];
+ }
+ }
+
+ void compute_deps(RTLIL::SigBit output, const pool<RTLIL::SigBit> &inputs)
+ {
+ sig2deps[output].insert(output);
+
+ RTLIL::Cell *cell = sig2driver.at(output);
+ RTLIL::SigBit sig_a = cell->getPort("\\A");
+ sig2deps[sig_a].reserve(sig2deps[sig_a].size() + sig2deps[output].size()); // Reserve so that any invalidation
+ // that may occur does so here, and
+ // not mid insertion (below)
+ sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end());
+ if (!inputs.count(sig_a))
+ compute_deps(sig_a, inputs);
+
+ if (cell->type == "$_AND_") {
+ RTLIL::SigSpec sig_b = cell->getPort("\\B");
+ sig2deps[sig_b].reserve(sig2deps[sig_b].size() + sig2deps[output].size()); // Reserve so that any invalidation
+ // that may occur does so here, and
+ // not mid insertion (below)
+ sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end());
+
+ if (!inputs.count(sig_b))
+ compute_deps(sig_b, inputs);
+ }
+ else if (cell->type == "$_NOT_") {
+ }
+ else log_abort();
+ }
+
+ bool eval(RTLIL::Cell *cell)
+ {
+ RTLIL::SigBit sig_y = cell->getPort("\\Y");
+ if (values_map.count(sig_y))
+ return true;
+
+ RTLIL::SigBit sig_a = cell->getPort("\\A");
+ if (!eval(sig_a))
+ return false;
+
+ RTLIL::State eval_ret = RTLIL::Sx;
+ if (cell->type == "$_NOT_") {
+ if (sig_a == State::S0) eval_ret = State::S1;
+ else if (sig_a == State::S1) eval_ret = State::S0;
+ }
+ else if (cell->type == "$_AND_") {
+ if (sig_a == State::S0) {
+ eval_ret = State::S0;
+ goto eval_end;
+ }
+
+ {
+ RTLIL::SigBit sig_b = cell->getPort("\\B");
+ if (!eval(sig_b))
+ return false;
+ if (sig_b == State::S0) {
+ eval_ret = State::S0;
+ goto eval_end;
+ }
+
+ if (sig_a != State::S1 || sig_b != State::S1)
+ goto eval_end;
+
+ eval_ret = State::S1;
+ }
+ }
+ else log_abort();
+
+eval_end:
+ set(sig_y, eval_ret);
+ return true;
+ }
+
+ bool eval(RTLIL::SigBit &sig)
+ {
+ auto it = values_map.find(sig);
+ if (it != values_map.end()) {
+ sig = it->second;
+ return true;
+ }
+
+ RTLIL::Cell *cell = sig2driver.at(sig);
+ if (!eval(cell))
+ return false;
+
+ it = values_map.find(sig);
+ if (it != values_map.end()) {
+ sig = it->second;
+ return true;
+ }
+
+ return false;
+ }
+};
+
+AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports)
+ : design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports)
{
module = new RTLIL::Module;
module->name = module_name;
@@ -73,6 +245,8 @@ end_of_header:
log_debug("M=%u I=%u L=%u O=%u A=%u B=%u C=%u J=%u F=%u\n", M, I, L, O, A, B, C, J, F);
line_count = 1;
+ piNum = 0;
+ flopNum = 0;
if (header == "aag")
parse_aiger_ascii();
@@ -81,20 +255,9 @@ end_of_header:
else
log_abort();
- RTLIL::Wire* n0 = module->wire("\\n0");
+ RTLIL::Wire* n0 = module->wire("\\__0__");
if (n0)
- module->connect(n0, RTLIL::S0);
-
- for (unsigned i = 0; i < outputs.size(); ++i) {
- RTLIL::Wire *wire = outputs[i];
- if (wire->port_input) {
- RTLIL::Wire *o_wire = module->addWire(wire->name.str() + "_o");
- o_wire->port_output = true;
- wire->port_output = false;
- module->connect(o_wire, wire);
- outputs[i] = o_wire;
- }
- }
+ module->connect(n0, State::S0);
// Parse footer (symbol table, comments, etc.)
unsigned l1;
@@ -131,36 +294,188 @@ end_of_header:
std::getline(f, line); // Ignore up to start of next line
}
- module->fixup_ports();
- design->add(module);
+ post_process();
+}
+
+static uint32_t parse_xaiger_literal(std::istream &f)
+{
+ uint32_t l;
+ f.read(reinterpret_cast<char*>(&l), sizeof(l));
+ if (f.gcount() != sizeof(l))
+#if defined(_WIN32) && defined(__MINGW32__)
+ log_error("Offset %I64d: unable to read literal!\n", static_cast<int64_t>(f.tellg()));
+#else
+ log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg()));
+#endif
+ return from_big_endian(l);
}
static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal)
{
const unsigned variable = literal >> 1;
const bool invert = literal & 1;
- RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix?
+ RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : ""));
RTLIL::Wire *wire = module->wire(wire_name);
if (wire) return wire;
- log_debug("Creating %s\n", wire_name.c_str());
+ log_debug2("Creating %s\n", wire_name.c_str());
wire = module->addWire(wire_name);
+ wire->port_input = wire->port_output = false;
if (!invert) return wire;
- RTLIL::IdString wire_inv_name(stringf("\\n%d", variable));
+ RTLIL::IdString wire_inv_name(stringf("\\__%d__", variable));
RTLIL::Wire *wire_inv = module->wire(wire_inv_name);
if (wire_inv) {
if (module->cell(wire_inv_name)) return wire;
}
else {
- log_debug("Creating %s\n", wire_inv_name.c_str());
+ log_debug2("Creating %s\n", wire_inv_name.c_str());
wire_inv = module->addWire(wire_inv_name);
+ wire_inv->port_input = wire_inv->port_output = false;
}
- log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str());
- module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix?
+ log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str());
+ module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire);
return wire;
}
+void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
+{
+ std::string header;
+ f >> header;
+ if (header != "aag" && header != "aig")
+ log_error("Unsupported AIGER file!\n");
+
+ // Parse rest of header
+ if (!(f >> M >> I >> L >> O >> A))
+ log_error("Invalid AIGER header\n");
+
+ // Optional values
+ B = C = J = F = 0;
+
+ std::string line;
+ std::getline(f, line); // Ignore up to start of next line, as standard
+ // says anything that follows could be used for
+ // optional sections
+
+ log_debug("M=%u I=%u L=%u O=%u A=%u\n", M, I, L, O, A);
+
+ line_count = 1;
+ piNum = 0;
+ flopNum = 0;
+
+ if (header == "aag")
+ parse_aiger_ascii();
+ else if (header == "aig")
+ parse_aiger_binary();
+ else
+ log_abort();
+
+ RTLIL::Wire* n0 = module->wire("\\__0__");
+ if (n0)
+ module->connect(n0, State::S0);
+
+ // Parse footer (symbol table, comments, etc.)
+ std::string s;
+ bool comment_seen = false;
+ for (int c = f.peek(); c != EOF; c = f.peek()) {
+ if (comment_seen || c == 'c') {
+ if (!comment_seen) {
+ f.ignore(1);
+ c = f.peek();
+ comment_seen = true;
+ }
+ if (c == '\n')
+ break;
+ f.ignore(1);
+ // XAIGER extensions
+ if (c == 'm') {
+ uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ uint32_t lutNum = parse_xaiger_literal(f);
+ uint32_t lutSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
+ ConstEvalAig ce(module);
+ for (unsigned i = 0; i < lutNum; ++i) {
+ uint32_t rootNodeID = parse_xaiger_literal(f);
+ uint32_t cutLeavesM = parse_xaiger_literal(f);
+ log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM);
+ RTLIL::Wire *output_sig = module->wire(stringf("\\__%d__", rootNodeID));
+ uint32_t nodeID;
+ RTLIL::SigSpec input_sig;
+ for (unsigned j = 0; j < cutLeavesM; ++j) {
+ nodeID = parse_xaiger_literal(f);
+ log_debug2("\t%u\n", nodeID);
+ RTLIL::Wire *wire = module->wire(stringf("\\__%d__", nodeID));
+ log_assert(wire);
+ input_sig.append(wire);
+ }
+ // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size())
+ ce.clear();
+ ce.compute_deps(output_sig, input_sig.to_sigbit_pool());
+ RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size());
+ for (int j = 0; j < (1 << cutLeavesM); ++j) {
+ int gray = j ^ (j >> 1);
+ ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast<int>(cutLeavesM)});
+ RTLIL::SigBit o(output_sig);
+ bool success YS_ATTRIBUTE(unused) = ce.eval(o);
+ log_assert(success);
+ log_assert(o.wire == nullptr);
+ lut_mask[gray] = o.data;
+ }
+ RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID));
+ log_assert(output_cell);
+ module->remove(output_cell);
+ module->addLut(stringf("\\__%d__$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask));
+ }
+ }
+ else if (c == 'r') {
+ uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ flopNum = parse_xaiger_literal(f);
+ log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
+ f.ignore(flopNum * sizeof(uint32_t));
+ }
+ else if (c == 'n') {
+ parse_xaiger_literal(f);
+ f >> s;
+ log_debug("n: '%s'\n", s.c_str());
+ }
+ else if (c == 'h') {
+ f.ignore(sizeof(uint32_t));
+ uint32_t version YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ log_assert(version == 1);
+ uint32_t ciNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ log_debug("ciNum = %u\n", ciNum);
+ uint32_t coNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ log_debug("coNum = %u\n", coNum);
+ piNum = parse_xaiger_literal(f);
+ log_debug("piNum = %u\n", piNum);
+ uint32_t poNum YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ log_debug("poNum = %u\n", poNum);
+ uint32_t boxNum = parse_xaiger_literal(f);
+ 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);
+ log_assert(boxUniqueId > 0);
+ uint32_t oldBoxNum = parse_xaiger_literal(f);
+ RTLIL::Cell* cell = module->addCell(stringf("$__box%u__", oldBoxNum), box_lookup.at(boxUniqueId));
+ boxes.emplace_back(cell);
+ }
+ }
+ else if (c == 'a' || c == 'i' || c == 'o') {
+ uint32_t dataSize = parse_xaiger_literal(f);
+ f.ignore(dataSize);
+ }
+ else {
+ break;
+ }
+ }
+ else
+ log_error("Line %u: cannot interpret first character '%c'!\n", line_count, c);
+ }
+
+ post_process();
+}
+
void AigerReader::parse_aiger_ascii()
{
std::string line;
@@ -172,8 +487,8 @@ void AigerReader::parse_aiger_ascii()
for (unsigned i = 1; i <= I; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an input!\n", line_count);
- log_debug("%d is an input\n", l1);
- log_assert(!(l1 & 1)); // TODO: Inputs can't be inverted?
+ log_debug2("%d is an input\n", l1);
+ log_assert(!(l1 & 1)); // Inputs can't be inverted
RTLIL::Wire *wire = createWireIfNotExists(module, l1);
wire->port_input = true;
inputs.push_back(wire);
@@ -182,17 +497,19 @@ void AigerReader::parse_aiger_ascii()
// Parse latches
RTLIL::Wire *clk_wire = nullptr;
if (L > 0) {
+ log_assert(clk_name != "");
clk_wire = module->wire(clk_name);
log_assert(!clk_wire);
- log_debug("Creating %s\n", clk_name.c_str());
+ log_debug2("Creating %s\n", clk_name.c_str());
clk_wire = module->addWire(clk_name);
clk_wire->port_input = true;
+ clk_wire->port_output = false;
}
for (unsigned i = 0; i < L; ++i, ++line_count) {
if (!(f >> l1 >> l2))
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
- log_debug("%d %d is a latch\n", l1, l2);
- log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted?
+ log_debug2("%d %d is a latch\n", l1, l2);
+ log_assert(!(l1 & 1));
RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
@@ -204,18 +521,18 @@ void AigerReader::parse_aiger_ascii()
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0)
- q_wire->attributes["\\init"] = RTLIL::S0;
+ q_wire->attributes["\\init"] = State::S0;
else if (l3 == 1)
- q_wire->attributes["\\init"] = RTLIL::S1;
+ q_wire->attributes["\\init"] = State::S1;
else if (l3 == l1) {
- //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
+ //q_wire->attributes["\\init"] = RTLIL::Sx;
}
else
log_error("Line %u has invalid reset literal for latch!\n", line_count);
}
else {
// AIGER latches are assumed to be initialized to zero
- q_wire->attributes["\\init"] = RTLIL::S0;
+ q_wire->attributes["\\init"] = State::S0;
}
latches.push_back(q_wire);
}
@@ -225,8 +542,18 @@ void AigerReader::parse_aiger_ascii()
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
- log_debug("%d is an output\n", l1);
- RTLIL::Wire *wire = createWireIfNotExists(module, l1);
+ log_debug2("%d is an output\n", l1);
+ const unsigned variable = l1 >> 1;
+ const bool invert = l1 & 1;
+ RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix?
+ RTLIL::Wire *wire = module->wire(wire_name);
+ if (!wire)
+ wire = createWireIfNotExists(module, l1);
+ else if (wire->port_input || wire->port_output) {
+ RTLIL::Wire *new_wire = module->addWire(NEW_ID);
+ module->connect(new_wire, wire);
+ wire = new_wire;
+ }
wire->port_output = true;
outputs.push_back(wire);
}
@@ -236,7 +563,7 @@ void AigerReader::parse_aiger_ascii()
if (!(f >> l1))
log_error("Line %u cannot be interpreted as a bad state property!\n", line_count);
- log_debug("%d is a bad state property\n", l1);
+ log_debug2("%d is a bad state property\n", l1);
RTLIL::Wire *wire = createWireIfNotExists(module, l1);
wire->port_output = true;
bad_properties.push_back(wire);
@@ -259,12 +586,12 @@ void AigerReader::parse_aiger_ascii()
if (!(f >> l1 >> l2 >> l3))
log_error("Line %u cannot be interpreted as an AND!\n", line_count);
- log_debug("%d %d %d is an AND\n", l1, l2, l3);
- log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted?
+ log_debug2("%d %d %d is an AND\n", l1, l2, l3);
+ log_assert(!(l1 & 1));
RTLIL::Wire *o_wire = createWireIfNotExists(module, l1);
RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2);
RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3);
- module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire);
+ module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire);
}
std::getline(f, line); // Ignore up to start of next line
}
@@ -285,19 +612,23 @@ void AigerReader::parse_aiger_binary()
// Parse inputs
for (unsigned i = 1; i <= I; ++i) {
+ log_debug2("%d is an input\n", i);
RTLIL::Wire *wire = createWireIfNotExists(module, i << 1);
wire->port_input = true;
+ log_assert(!wire->port_output);
inputs.push_back(wire);
}
// Parse latches
RTLIL::Wire *clk_wire = nullptr;
if (L > 0) {
+ log_assert(clk_name != "");
clk_wire = module->wire(clk_name);
log_assert(!clk_wire);
- log_debug("Creating %s\n", clk_name.c_str());
+ log_debug2("Creating %s\n", clk_name.c_str());
clk_wire = module->addWire(clk_name);
clk_wire->port_input = true;
+ clk_wire->port_output = false;
}
l1 = (I+1) * 2;
for (unsigned i = 0; i < L; ++i, ++line_count, l1 += 2) {
@@ -315,18 +646,18 @@ void AigerReader::parse_aiger_binary()
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0)
- q_wire->attributes["\\init"] = RTLIL::S0;
+ q_wire->attributes["\\init"] = State::S0;
else if (l3 == 1)
- q_wire->attributes["\\init"] = RTLIL::S1;
+ q_wire->attributes["\\init"] = State::S1;
else if (l3 == l1) {
- //q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
+ //q_wire->attributes["\\init"] = RTLIL::Sx;
}
else
log_error("Line %u has invalid reset literal for latch!\n", line_count);
}
else {
// AIGER latches are assumed to be initialized to zero
- q_wire->attributes["\\init"] = RTLIL::S0;
+ q_wire->attributes["\\init"] = State::S0;
}
latches.push_back(q_wire);
}
@@ -336,8 +667,18 @@ void AigerReader::parse_aiger_binary()
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an output!\n", line_count);
- log_debug("%d is an output\n", l1);
- RTLIL::Wire *wire = createWireIfNotExists(module, l1);
+ log_debug2("%d is an output\n", l1);
+ const unsigned variable = l1 >> 1;
+ const bool invert = l1 & 1;
+ RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "_b" the right suffix?
+ RTLIL::Wire *wire = module->wire(wire_name);
+ if (!wire)
+ wire = createWireIfNotExists(module, l1);
+ else if (wire->port_input || wire->port_output) {
+ RTLIL::Wire *new_wire = module->addWire(NEW_ID);
+ module->connect(new_wire, wire);
+ wire = new_wire;
+ }
wire->port_output = true;
outputs.push_back(wire);
}
@@ -348,7 +689,7 @@ void AigerReader::parse_aiger_binary()
if (!(f >> l1))
log_error("Line %u cannot be interpreted as a bad state property!\n", line_count);
- log_debug("%d is a bad state property\n", l1);
+ log_debug2("%d is a bad state property\n", l1);
RTLIL::Wire *wire = createWireIfNotExists(module, l1);
wire->port_output = true;
bad_properties.push_back(wire);
@@ -374,16 +715,278 @@ void AigerReader::parse_aiger_binary()
l2 = parse_next_delta_literal(f, l1);
l3 = parse_next_delta_literal(f, l2);
- log_debug("%d %d %d is an AND\n", l1, l2, l3);
- log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted?
+ log_debug2("%d %d %d is an AND\n", l1, l2, l3);
+ log_assert(!(l1 & 1));
RTLIL::Wire *o_wire = createWireIfNotExists(module, l1);
RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2);
RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3);
+ module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire);
+ }
+}
+
+void AigerReader::post_process()
+{
+ pool<IdString> seen_boxes;
+ unsigned ci_count = 0, co_count = 0;
+ for (auto cell : boxes) {
+ RTLIL::Module* box_module = design->module(cell->type);
+ log_assert(box_module);
+
+ 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;
+ 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));
+ 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());
+
+ 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());
- RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_");
- and_cell->setPort("\\A", i1_wire);
- and_cell->setPort("\\B", i2_wire);
- and_cell->setPort("\\Y", o_wire);
+ auto &ports = box_module->ports;
+ for (auto jt = ports.begin(); jt != ports.end(); ) {
+ RTLIL::Wire* w = box_module->wire(*jt);
+ log_assert(w);
+ if (w == carry_in || w == carry_out) {
+ jt = ports.erase(jt);
+ continue;
+ }
+ if (w->port_id > carry_in->port_id)
+ --w->port_id;
+ if (w->port_id > carry_out->port_id)
+ --w->port_id;
+ log_assert(w->port_input || w->port_output);
+ log_assert(ports[w->port_id-1] == w->name);
+ ++jt;
+ }
+ ports.push_back(carry_in->name);
+ carry_in->port_id = ports.size();
+ ports.push_back(carry_out->name);
+ carry_out->port_id = ports.size();
+ }
+ }
+
+ // 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::SigSpec rhs;
+ RTLIL::Wire* wire = nullptr;
+ for (int i = 0; i < GetSize(w); i++) {
+ if (w->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 (w->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;
+ }
+ rhs.append(wire);
+ }
+ cell->setPort(port_name, rhs);
+ }
+ }
+
+ dict<RTLIL::IdString, int> wideports_cache;
+
+ if (!map_filename.empty()) {
+ std::ifstream mf(map_filename);
+ std::string type, symbol;
+ int variable, index;
+ while (mf >> type >> variable >> index >> symbol) {
+ RTLIL::IdString escaped_s = RTLIL::escape_id(symbol);
+ if (type == "input") {
+ log_assert(static_cast<unsigned>(variable) < inputs.size());
+ RTLIL::Wire* wire = inputs[variable];
+ log_assert(wire);
+ log_assert(wire->port_input);
+
+ if (index == 0) {
+ // Cope with the fact that a CI might be identical
+ // to a PI (necessary due to ABC); in those cases
+ // simply connect the latter to the former
+ RTLIL::Wire* existing = module->wire(escaped_s);
+ if (!existing)
+ module->rename(wire, escaped_s);
+ else {
+ wire->port_input = false;
+ module->connect(wire, existing);
+ }
+ }
+ else if (index > 0) {
+ std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
+ RTLIL::Wire* existing = module->wire(indexed_name);
+ if (!existing) {
+ module->rename(wire, indexed_name);
+ if (wideports)
+ wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
+ }
+ else {
+ module->connect(wire, existing);
+ wire->port_input = false;
+ }
+ }
+ }
+ else if (type == "output") {
+ log_assert(static_cast<unsigned>(variable + co_count) < outputs.size());
+ RTLIL::Wire* wire = outputs[variable + co_count];
+ log_assert(wire);
+ log_assert(wire->port_output);
+ if (escaped_s == "$__dummy__") {
+ wire->port_output = false;
+ continue;
+ }
+
+ if (index == 0) {
+ // Cope with the fact that a CO might be identical
+ // to a PO (necessary due to ABC); in those cases
+ // simply connect the latter to the former
+ RTLIL::Wire* existing = module->wire(escaped_s);
+ 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));
+ log_assert(in_wire);
+ log_assert(in_wire->port_input && !in_wire->port_output);
+ in_wire->port_output = true;
+ module->connect(in_wire, wire);
+ }
+ else
+ module->rename(wire, escaped_s);
+ }
+ else {
+ wire->port_output = false;
+ module->connect(wire, existing);
+ }
+ }
+ else if (index > 0) {
+ std::string indexed_name = stringf("%s[%d]", escaped_s.c_str(), index);
+ RTLIL::Wire* existing = module->wire(indexed_name);
+ 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));
+ log_assert(in_wire);
+ log_assert(in_wire->port_input && !in_wire->port_output);
+ in_wire->port_output = true;
+ module->connect(in_wire, wire);
+ }
+ else {
+ module->rename(wire, indexed_name);
+ if (wideports)
+ wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
+ }
+ }
+ else {
+ module->connect(wire, existing);
+ wire->port_output = false;
+ }
+ }
+ }
+ else if (type == "box") {
+ RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
+ if (cell) { // ABC could have optimised this box away
+ module->rename(cell, escaped_s);
+ for (const auto &i : cell->connections()) {
+ RTLIL::IdString port_name = i.first;
+ RTLIL::SigSpec rhs = i.second;
+ int index = 0;
+ for (auto bit : rhs.bits()) {
+ RTLIL::Wire* wire = bit.wire;
+ RTLIL::IdString escaped_s = RTLIL::escape_id(stringf("%s.%s", log_id(cell), log_id(port_name)));
+ if (index == 0)
+ module->rename(wire, escaped_s);
+ else if (index > 0) {
+ module->rename(wire, stringf("%s[%d]", escaped_s.c_str(), index));
+ if (wideports)
+ wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);
+ }
+ index++;
+ }
+ }
+ }
+ }
+ else
+ log_error("Symbol type '%s' not recognised.\n", type.c_str());
+ }
+ }
+
+ for (auto &wp : wideports_cache) {
+ auto name = wp.first;
+ int width = wp.second + 1;
+
+ RTLIL::Wire *wire = module->wire(name);
+ if (wire)
+ module->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name.c_str(), 0)));
+
+ // Do not make ports with a mix of input/output into
+ // wide ports
+ bool port_input = false, port_output = false;
+ for (int i = 0; i < width; i++) {
+ RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
+ RTLIL::Wire *other_wire = module->wire(other_name);
+ if (other_wire) {
+ port_input = port_input || other_wire->port_input;
+ port_output = port_output || other_wire->port_output;
+ }
+ }
+
+ wire = module->addWire(name, width);
+ wire->port_input = port_input;
+ wire->port_output = port_output;
+
+ for (int i = 0; i < width; i++) {
+ RTLIL::IdString other_name = name.str() + stringf("[%d]", i);
+ RTLIL::Wire *other_wire = module->wire(other_name);
+ if (other_wire) {
+ other_wire->port_input = false;
+ other_wire->port_output = false;
+ }
+ if (wire->port_input) {
+ if (other_wire)
+ module->connect(other_wire, SigSpec(wire, i));
+ }
+ else {
+ // Since we skip POs that are connected to Sx,
+ // re-connect them here
+ module->connect(SigSpec(wire, i), other_wire ? other_wire : SigSpec(RTLIL::Sx));
+ }
+ }
+ }
+
+ module->fixup_ports();
+
+ // Insert into a new (temporary) design so that "clean" will only
+ // operate (and run checks on) this one module
+ RTLIL::Design *mapped_design = new RTLIL::Design;
+ mapped_design->add(module);
+ Pass::call(mapped_design, "clean");
+ mapped_design->modules_.erase(module->name);
+ delete mapped_design;
+
+ design->add(module);
+
+ for (auto cell : module->cells().to_vector()) {
+ if (cell->type != "$lut") continue;
+ auto y_port = cell->getPort("\\Y").as_bit();
+ if (y_port.wire->width == 1)
+ module->rename(cell, stringf("%s$lut", y_port.wire->name.c_str()));
+ else
+ module->rename(cell, stringf("%s[%d]$lut", y_port.wire->name.c_str(), y_port.offset));
}
}
@@ -398,18 +1001,19 @@ struct AigerFrontend : public Frontend {
log("Load module from an AIGER file into the current design.\n");
log("\n");
log(" -module_name <module_name>\n");
- log(" Name of module to be created (default: "
-#ifdef _WIN32
- "top" // FIXME
-#else
- "<filename>"
-#endif
- ")\n");
+ log(" Name of module to be created (default: <filename>)\n");
log("\n");
log(" -clk_name <wire_name>\n");
log(" AIGER latches to be transformed into posedge DFFs clocked by wire of");
log(" this name (default: clk)\n");
log("\n");
+ log(" -map <filename>\n");
+ log(" read file with port and latch symbols\n");
+ log("\n");
+ log(" -wideports\n");
+ log(" Merge ports that match the pattern 'name[int]' into a single\n");
+ log(" multi-bit port 'name'.\n");
+ log("\n");
}
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
@@ -417,6 +1021,8 @@ struct AigerFrontend : public Frontend {
RTLIL::IdString clk_name = "\\clk";
RTLIL::IdString module_name;
+ std::string map_filename;
+ bool wideports = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -429,13 +1035,23 @@ struct AigerFrontend : public Frontend {
clk_name = RTLIL::escape_id(args[++argidx]);
continue;
}
+ if (map_filename.empty() && arg == "-map" && argidx+1 < args.size()) {
+ map_filename = args[++argidx];
+ continue;
+ }
+ if (arg == "-wideports") {
+ wideports = true;
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);
if (module_name.empty()) {
#ifdef _WIN32
- module_name = "top"; // FIXME: basename equivalent on Win32?
+ char fname[_MAX_FNAME];
+ _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */);
+ module_name = fname;
#else
char* bn = strdup(filename.c_str());
module_name = RTLIL::escape_id(bn);
@@ -443,7 +1059,7 @@ struct AigerFrontend : public Frontend {
#endif
}
- AigerReader reader(design, *f, module_name, clk_name);
+ AigerReader reader(design, *f, module_name, clk_name, map_filename, wideports);
reader.parse_aiger();
}
} AigerFrontend;
diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h
index 0e3719cc4..583c9d0f9 100644
--- a/frontends/aiger/aigerparse.h
+++ b/frontends/aiger/aigerparse.h
@@ -2,7 +2,7 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Eddie Hung <eddie@fpgeh.com>
+ * 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -31,20 +31,26 @@ struct AigerReader
std::istream &f;
RTLIL::IdString clk_name;
RTLIL::Module *module;
+ std::string map_filename;
+ bool wideports;
unsigned M, I, L, O, A;
unsigned B, C, J, F; // Optional in AIGER 1.9
unsigned line_count;
+ uint32_t piNum, flopNum;
std::vector<RTLIL::Wire*> inputs;
std::vector<RTLIL::Wire*> latches;
std::vector<RTLIL::Wire*> outputs;
std::vector<RTLIL::Wire*> bad_properties;
+ std::vector<RTLIL::Cell*> boxes;
- AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name);
+ AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
void parse_aiger();
+ void parse_xaiger(const dict<int,IdString> &box_lookup);
void parse_aiger_ascii();
void parse_aiger_binary();
+ void post_process();
};
YOSYS_NAMESPACE_END
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 3d066af53..82283fb5b 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -283,8 +283,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
if (!bits.empty()) {
fprintf(f, " bits='");
for (size_t i = bits.size(); i > 0; i--)
- fprintf(f, "%c", bits[i-1] == RTLIL::S0 ? '0' :
- bits[i-1] == RTLIL::S1 ? '1' :
+ fprintf(f, "%c", bits[i-1] == State::S0 ? '0' :
+ bits[i-1] == State::S1 ? '1' :
bits[i-1] == RTLIL::Sx ? 'x' :
bits[i-1] == RTLIL::Sz ? 'z' : '?');
fprintf(f, "'(%d)", GetSize(bits));
@@ -716,7 +716,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
node->integer = v;
node->is_signed = is_signed;
for (int i = 0; i < width; i++) {
- node->bits.push_back((v & 1) ? RTLIL::S1 : RTLIL::S0);
+ node->bits.push_back((v & 1) ? State::S1 : State::S0);
v = v >> 1;
}
node->range_valid = true;
@@ -733,9 +733,9 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
node->bits = v;
for (size_t i = 0; i < 32; i++) {
if (i < node->bits.size())
- node->integer |= (node->bits[i] == RTLIL::S1) << i;
+ node->integer |= (node->bits[i] == State::S1) << i;
else if (is_signed && !node->bits.empty())
- node->integer |= (node->bits.back() == RTLIL::S1) << i;
+ node->integer |= (node->bits.back() == State::S1) << i;
}
node->range_valid = true;
node->range_left = node->bits.size()-1;
@@ -767,7 +767,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
for (size_t i = 0; i < str.size(); i++) {
unsigned char ch = str[str.size() - i - 1];
for (int j = 0; j < 8; j++) {
- data.push_back((ch & 1) ? RTLIL::S1 : RTLIL::S0);
+ data.push_back((ch & 1) ? State::S1 : State::S0);
ch = ch >> 1;
}
}
@@ -780,7 +780,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
bool AstNode::bits_only_01() const
{
for (auto bit : bits)
- if (bit != RTLIL::S0 && bit != RTLIL::S1)
+ if (bit != State::S0 && bit != State::S1)
return false;
return true;
}
@@ -1164,7 +1164,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
}
}
- if (flag_icells && (*it)->str.substr(0, 2) == "\\$")
+ if (flag_icells && (*it)->str.compare(0, 2, "\\$") == 0)
(*it)->str = (*it)->str.substr(1);
if (defer)
@@ -1172,7 +1172,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
if (design->has((*it)->str)) {
RTLIL::Module *existing_mod = design->module((*it)->str);
- if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
+ if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s:%d.\n",
@@ -1463,7 +1463,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
{
std::string stripped_name = name.str();
- if (stripped_name.substr(0, 9) == "$abstract")
+ 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());
@@ -1502,7 +1502,10 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
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_STRING) != 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);
@@ -1551,7 +1554,9 @@ RTLIL::Module *AstModule::clone() const
new_mod->nomeminit = nomeminit;
new_mod->nomem2reg = nomem2reg;
new_mod->mem2reg = mem2reg;
+ new_mod->noblackbox = noblackbox;
new_mod->lib = lib;
+ new_mod->nowb = nowb;
new_mod->noopt = noopt;
new_mod->icells = icells;
new_mod->pwires = pwires;
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 079fc11e5..407a34472 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -504,6 +504,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule;
+ current_case->attributes["\\src"] = stringf("%s:%d", child->filename.c_str(), child->linenum);
last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
for (auto node : child->children) {
@@ -1515,7 +1516,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
AstNode *child = *it;
if (child->type == AST_CELLTYPE) {
cell->type = child->str;
- if (flag_icells && cell->type.substr(0, 2) == "\\$")
+ if (flag_icells && cell->type.begins_with("\\$"))
cell->type = cell->type.substr(1);
continue;
}
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index e947125bf..86dd80c65 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -150,6 +150,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
reg->str = stringf("%s[%d]", node->str.c_str(), i);
reg->is_reg = true;
reg->is_signed = node->is_signed;
+ for (auto &it : node->attributes)
+ if (it.first != ID(mem2reg))
+ reg->attributes.emplace(it.first, it.second->clone());
+ reg->filename = node->filename;
+ reg->linenum = node->linenum;
children.push_back(reg);
while (reg->simplify(true, false, false, 1, -1, false, false)) { }
}
@@ -2319,7 +2324,7 @@ skip_dynamic_range_lvalue_expansion:;
if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0)
{
AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone());
- cell_arg->str = RTLIL::escape_id(attr.first.str().substr(strlen("\\via_celltype_defparam_")));
+ cell_arg->str = RTLIL::escape_id(attr.first.substr(strlen("\\via_celltype_defparam_")));
cell->children.push_back(cell_arg);
}
@@ -2793,13 +2798,13 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
std::getline(f, line);
for (int i = 0; i < GetSize(line); i++) {
- if (in_comment && line.substr(i, 2) == "*/") {
+ if (in_comment && line.compare(i, 2, "*/") == 0) {
line[i] = ' ';
line[i+1] = ' ';
in_comment = false;
continue;
}
- if (!in_comment && line.substr(i, 2) == "/*")
+ if (!in_comment && line.compare(i, 2, "/*") == 0)
in_comment = true;
if (in_comment)
line[i] = ' ';
@@ -2808,7 +2813,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
while (1)
{
token = next_token(line, " \t\r\n");
- if (token.empty() || token.substr(0, 2) == "//")
+ if (token.empty() || token.compare(0, 2, "//") == 0)
break;
if (token[0] == '@') {
@@ -3439,19 +3444,11 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
{
std::map<std::string, AstNode*> backup_scope;
std::map<std::string, AstNode::varinfo_t> variables;
- bool delete_temp_block = false;
- AstNode *block = NULL;
+ AstNode *block = new AstNode(AST_BLOCK);
size_t argidx = 0;
for (auto child : children)
{
- if (child->type == AST_BLOCK)
- {
- log_assert(block == NULL);
- block = child;
- continue;
- }
-
if (child->type == AST_WIRE)
{
while (child->simplify(true, false, false, 1, -1, false, true)) { }
@@ -3468,13 +3465,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue;
}
- log_assert(block == NULL);
- delete_temp_block = true;
- block = new AstNode(AST_BLOCK);
block->children.push_back(child->clone());
}
- log_assert(block != NULL);
log_assert(variables.count(str) != 0);
while (!block->children.empty())
@@ -3642,8 +3635,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
log_abort();
}
- if (delete_temp_block)
- delete block;
+ delete block;
for (auto &it : backup_scope)
if (it.second == NULL)
diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc
index a6a07863f..d17cacf29 100644
--- a/frontends/blif/blifparse.cc
+++ b/frontends/blif/blifparse.cc
@@ -78,7 +78,7 @@ failed:
return std::pair<RTLIL::IdString, int>("\\" + name, 0);
}
-void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bool run_clean, bool sop_mode, bool wideports)
+void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool run_clean, bool sop_mode, bool wideports)
{
RTLIL::Module *module = nullptr;
RTLIL::Const *lutptr = NULL;
diff --git a/frontends/blif/blifparse.h b/frontends/blif/blifparse.h
index 955b6aacf..2b84cb795 100644
--- a/frontends/blif/blifparse.h
+++ b/frontends/blif/blifparse.h
@@ -24,7 +24,7 @@
YOSYS_NAMESPACE_BEGIN
-extern void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name,
+extern void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name,
bool run_clean = false, bool sop_mode = false, bool wideports = false);
YOSYS_NAMESPACE_END
diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y
index 44c99906a..b4b9693da 100644
--- a/frontends/ilang/ilang_parser.y
+++ b/frontends/ilang/ilang_parser.y
@@ -282,14 +282,14 @@ proc_stmt:
} case_body sync_list TOK_END EOL;
switch_stmt:
- attr_list TOK_SWITCH sigspec EOL {
+ TOK_SWITCH sigspec EOL {
RTLIL::SwitchRule *rule = new RTLIL::SwitchRule;
- rule->signal = *$3;
+ rule->signal = *$2;
rule->attributes = attrbuf;
switch_stack.back()->push_back(rule);
attrbuf.clear();
- delete $3;
- } switch_body TOK_END EOL;
+ delete $2;
+ } attr_list switch_body TOK_END EOL;
attr_list:
/* empty */ |
@@ -298,9 +298,11 @@ attr_list:
switch_body:
switch_body TOK_CASE {
RTLIL::CaseRule *rule = new RTLIL::CaseRule;
+ rule->attributes = attrbuf;
switch_stack.back()->back()->cases.push_back(rule);
switch_stack.push_back(&rule->switches);
case_stack.push_back(rule);
+ attrbuf.clear();
} compare_list EOL case_body {
switch_stack.pop_back();
case_stack.pop_back();
@@ -319,12 +321,15 @@ compare_list:
/* empty */;
case_body:
+ case_body attr_stmt |
case_body switch_stmt |
case_body assign_stmt |
/* empty */;
assign_stmt:
TOK_ASSIGN sigspec sigspec EOL {
+ if (attrbuf.size() != 0)
+ rtlil_frontend_ilang_yyerror("dangling attribute");
case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3));
delete $2;
delete $3;
diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc
index 82361ea9b..7aceffbfc 100644
--- a/frontends/json/jsonparse.cc
+++ b/frontends/json/jsonparse.cc
@@ -25,7 +25,7 @@ struct JsonNode
{
char type; // S=String, N=Number, A=Array, D=Dict
string data_string;
- int data_number;
+ int64_t data_number;
vector<JsonNode*> data_array;
dict<string, JsonNode*> data_dict;
vector<string> data_dict_keys;
@@ -206,6 +206,38 @@ struct JsonNode
}
};
+Const json_parse_attr_param_value(JsonNode *node)
+{
+ Const value;
+
+ if (node->type == 'S') {
+ string &s = node->data_string;
+ size_t cursor = s.find_first_not_of("01xz");
+ if (cursor == string::npos) {
+ value = Const::from_string(s);
+ } else if (s.find_first_not_of(' ', cursor) == string::npos) {
+ value = Const(s.substr(0, GetSize(s)-1));
+ } else {
+ value = Const(s);
+ }
+ } else
+ if (node->type == 'N') {
+ value = Const(node->data_number, 32);
+ if (node->data_number < 0)
+ value.flags |= RTLIL::CONST_FLAG_SIGNED;
+ } else
+ if (node->type == 'A') {
+ log_error("JSON attribute or parameter value is an array.\n");
+ } else
+ if (node->type == 'D') {
+ log_error("JSON attribute or parameter value is a dict.\n");
+ } else {
+ log_abort();
+ }
+
+ return value;
+}
+
void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
{
if (node->type != 'D')
@@ -214,28 +246,7 @@ void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
for (auto it : node->data_dict)
{
IdString key = RTLIL::escape_id(it.first.c_str());
- JsonNode *value_node = it.second;
- Const value;
-
- if (value_node->type == 'S') {
- string &s = value_node->data_string;
- if (s.find_first_not_of("01xz") == string::npos)
- value = Const::from_string(s);
- else
- value = Const(s);
- } else
- if (value_node->type == 'N') {
- value = Const(value_node->data_number, 32);
- } else
- if (value_node->type == 'A') {
- log_error("JSON attribute or parameter value is an array.\n");
- } else
- if (value_node->type == 'D') {
- log_error("JSON attribute or parameter value is a dict.\n");
- } else {
- log_abort();
- }
-
+ Const value = json_parse_attr_param_value(it.second);
results[key] = value;
}
}
@@ -292,6 +303,18 @@ void json_import(Design *design, string &modname, JsonNode *node)
if (port_wire == nullptr)
port_wire = module->addWire(port_name, GetSize(port_bits_node->data_array));
+ if (port_node->data_dict.count("upto") != 0) {
+ JsonNode *val = port_node->data_dict.at("upto");
+ if (val->type == 'N')
+ port_wire->upto = val->data_number != 0;
+ }
+
+ if (port_node->data_dict.count("offset") != 0) {
+ JsonNode *val = port_node->data_dict.at("offset");
+ if (val->type == 'N')
+ port_wire->start_offset = val->data_number;
+ }
+
if (port_direction_node->data_string == "input") {
port_wire->port_input = true;
} else
@@ -372,6 +395,18 @@ void json_import(Design *design, string &modname, JsonNode *node)
if (wire == nullptr)
wire = module->addWire(net_name, GetSize(bits_node->data_array));
+ if (net_node->data_dict.count("upto") != 0) {
+ JsonNode *val = net_node->data_dict.at("upto");
+ if (val->type == 'N')
+ wire->upto = val->data_number != 0;
+ }
+
+ if (net_node->data_dict.count("offset") != 0) {
+ JsonNode *val = net_node->data_dict.at("offset");
+ if (val->type == 'N')
+ wire->start_offset = val->data_number;
+ }
+
for (int i = 0; i < GetSize(bits_node->data_array); i++)
{
JsonNode *bitval_node = bits_node->data_array.at(i);
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index 6e3cffaca..14de95e07 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -551,7 +551,7 @@ struct LibertyFrontend : public Frontend {
if (design->has(cell_name)) {
Module *existing_mod = design->module(cell_name);
if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
- log_error("Re-definition of of cell/module %s!\n", log_id(cell_name));
+ log_error("Re-definition of cell/module %s!\n", log_id(cell_name));
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", log_id(cell_name));
continue;
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index 2bf99e58e..c5eef4b55 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>
@@ -111,9 +112,10 @@ string get_full_netlist_name(Netlist *nl)
// ==================================================================
-VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover) :
+VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit) :
mode_gates(mode_gates), mode_keep(mode_keep), mode_nosva(mode_nosva),
- mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover)
+ mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover),
+ mode_fullinit(mode_fullinit)
{
}
@@ -1454,6 +1456,50 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
merge_past_ffs(past_ffs);
}
+
+ if (!mode_fullinit)
+ {
+ pool<SigBit> non_ff_bits;
+ CellTypes ff_types;
+
+ ff_types.setup_internals_ff();
+ ff_types.setup_stdcells_mem();
+
+ for (auto cell : module->cells())
+ {
+ if (ff_types.cell_known(cell->type))
+ continue;
+
+ for (auto conn : cell->connections())
+ {
+ if (!cell->output(conn.first))
+ continue;
+
+ for (auto bit : conn.second)
+ if (bit.wire != nullptr)
+ non_ff_bits.insert(bit);
+ }
+ }
+
+ for (auto wire : module->wires())
+ {
+ if (!wire->attributes.count("\\init"))
+ continue;
+
+ Const &initval = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(initval); i++)
+ {
+ if (initval[i] != State::S0 && initval[i] != State::S1)
+ continue;
+
+ if (non_ff_bits.count(SigBit(wire, i)))
+ initval[i] = State::Sx;
+ }
+
+ if (initval.is_fully_undef())
+ wire->attributes.erase("\\init");
+ }
+ }
}
// ==================================================================
@@ -1743,7 +1789,7 @@ struct VerificExtNets
new_net = new Net(name.c_str());
nl->Add(new_net);
- Net *n = route_up(new_net, port->IsOutput(), ca_nl, ca_net);
+ Net *n YS_ATTRIBUTE(unused) = route_up(new_net, port->IsOutput(), ca_nl, ca_net);
log_assert(n == ca_net);
}
@@ -1829,7 +1875,7 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
while (!nl_todo.empty()) {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) {
- VerificImporter importer(false, false, false, false, false, false);
+ VerificImporter importer(false, false, false, false, false, false, false);
importer.import_netlist(design, nl, nl_todo);
}
nl_todo.erase(nl);
@@ -1952,6 +1998,9 @@ struct VerificPass : public Pass {
log(" -autocover\n");
log(" Generate automatic cover statements for all asserts\n");
log("\n");
+ log(" -fullinit\n");
+ log(" Keep all register initializations, even those for non-FF registers.\n");
+ log("\n");
log(" -chparam name value \n");
log(" Elaborate the specified top modules (all modules when -all given) using\n");
log(" this parameter value. Modules on which this parameter does not exist will\n");
@@ -2140,7 +2189,7 @@ struct VerificPass : public Pass {
veri_file::DefineMacro("VERIFIC");
veri_file::DefineMacro(args[argidx] == "-formal" ? "FORMAL" : "SYNTHESIS");
- for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].substr(0, 2) == "-D"; argidx++) {
+ for (argidx++; argidx < GetSize(args) && GetSize(args[argidx]) >= 2 && args[argidx].compare(0, 2, "-D") == 0; argidx++) {
std::string name = args[argidx].substr(2);
if (args[argidx] == "-D") {
if (++argidx >= GetSize(args))
@@ -2213,7 +2262,7 @@ struct VerificPass : public Pass {
std::set<Netlist*> nl_todo, nl_done;
bool mode_all = false, mode_gates = false, mode_keep = false;
bool mode_nosva = false, mode_names = false, mode_verific = false;
- bool mode_autocover = false;
+ bool mode_autocover = false, mode_fullinit = false;
bool flatten = false, extnets = false;
string dumpfile;
Map parameters(STRING_HASH);
@@ -2255,6 +2304,10 @@ struct VerificPass : public Pass {
mode_autocover = true;
continue;
}
+ if (args[argidx] == "-fullinit") {
+ mode_fullinit = true;
+ continue;
+ }
if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) {
const std::string &key = args[++argidx];
const std::string &value = args[++argidx];
@@ -2283,7 +2336,7 @@ struct VerificPass : public Pass {
break;
}
- if (argidx > GetSize(args) && args[argidx].substr(0, 1) == "-")
+ if (argidx > GetSize(args) && args[argidx].compare(0, 1, "-") == 0)
cmd_error(args, argidx, "unknown option");
if (mode_all)
@@ -2378,7 +2431,7 @@ struct VerificPass : public Pass {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) {
VerificImporter importer(mode_gates, mode_keep, mode_nosva,
- mode_names, mode_verific, mode_autocover);
+ mode_names, mode_verific, mode_autocover, mode_fullinit);
importer.import_netlist(design, nl, nl_todo);
}
nl_todo.erase(nl);
@@ -2484,7 +2537,7 @@ struct ReadPass : public Pass {
args[0] = "verific";
} else {
args[0] = "read_verilog";
- args.erase(args.begin()+1, args.begin()+2);
+ args[1] = "-defer";
}
Pass::call(design, args);
return;
@@ -2498,6 +2551,7 @@ struct ReadPass : public Pass {
if (args[1] == "-formal")
args.insert(args.begin()+1, std::string());
args[1] = "-sv";
+ args.insert(args.begin()+1, "-defer");
}
Pass::call(design, args);
return;
diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h
index 88a6cc0ba..5cbd78f7b 100644
--- a/frontends/verific/verific.h
+++ b/frontends/verific/verific.h
@@ -72,9 +72,9 @@ struct VerificImporter
pool<Verific::Net*, hash_ptr_ops> any_all_nets;
bool mode_gates, mode_keep, mode_nosva, mode_names, mode_verific;
- bool mode_autocover;
+ bool mode_autocover, mode_fullinit;
- VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover);
+ VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit);
RTLIL::SigBit net_map_at(Verific::Net *net);
diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc
index 8ea8372d3..909e9b4f1 100644
--- a/frontends/verific/verificsva.cc
+++ b/frontends/verific/verificsva.cc
@@ -357,7 +357,7 @@ struct SvaFsm
for (int i = 0; i < GetSize(nodes); i++)
{
if (next_state_sig[i] != State::S0) {
- clocking.addDff(NEW_ID, next_state_sig[i], state_wire[i], Const(0, 1));
+ clocking.addDff(NEW_ID, next_state_sig[i], state_wire[i], State::S0);
} else {
module->connect(state_wire[i], State::S0);
}
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc
index 57d366dbf..4bf5b1cf5 100644
--- a/frontends/verilog/const2ast.cc
+++ b/frontends/verilog/const2ast.cc
@@ -99,7 +99,7 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
if (base == 10) {
while (!digits.empty())
- data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
+ data.push_back(my_decimal_div_by_two(digits) ? State::S1 : State::S0);
} else {
int bits_per_digit = my_ilog2(base-1);
for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) {
@@ -115,17 +115,17 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
else if (*it == 0xf2)
data.push_back(RTLIL::Sa);
else
- data.push_back((*it & bitmask) ? RTLIL::S1 : RTLIL::S0);
+ data.push_back((*it & bitmask) ? State::S1 : State::S0);
}
}
}
int len = GetSize(data);
- RTLIL::State msb = data.empty() ? RTLIL::S0 : data.back();
+ RTLIL::State msb = data.empty() ? State::S0 : data.back();
if (len_in_bits < 0) {
if (len < 32)
- data.resize(32, msb == RTLIL::S0 || msb == RTLIL::S1 ? RTLIL::S0 : msb);
+ data.resize(32, msb == State::S0 || msb == State::S1 ? RTLIL::S0 : msb);
return;
}
@@ -133,11 +133,11 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len);
for (len = len - 1; len >= 0; len--)
- if (data[len] == RTLIL::S1)
+ if (data[len] == State::S1)
break;
- if (msb == RTLIL::S0 || msb == RTLIL::S1) {
+ if (msb == State::S0 || msb == State::S1) {
len += 1;
- data.resize(len_in_bits, RTLIL::S0);
+ data.resize(len_in_bits, State::S0);
} else {
len += 2;
data.resize(len_in_bits, msb);
@@ -153,7 +153,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
{
if (warn_z) {
AstNode *ret = const2ast(code, case_type);
- if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end())
+ if (ret != nullptr && std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end())
log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n",
current_filename.c_str(), get_line_num());
return ret;
@@ -169,7 +169,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
for (int i = 0; i < len; i++) {
unsigned char ch = str[len - i];
for (int j = 0; j < 8; j++) {
- data.push_back((ch & 1) ? RTLIL::S1 : RTLIL::S0);
+ data.push_back((ch & 1) ? State::S1 : State::S0);
ch = ch >> 1;
}
}
@@ -190,8 +190,8 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
if (*endptr == 0) {
std::vector<RTLIL::State> data;
my_strtobin(data, str, -1, 10, case_type, false);
- if (data.back() == RTLIL::S1)
- data.push_back(RTLIL::S0);
+ if (data.back() == State::S1)
+ data.push_back(State::S0);
return AstNode::mkconst_bits(data, true);
}
@@ -204,7 +204,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
{
std::vector<RTLIL::State> data;
bool is_signed = false;
- bool is_unsized = false;
+ bool is_unsized = len_in_bits < 0;
if (*(endptr+1) == 's') {
is_signed = true;
endptr++;
@@ -213,32 +213,32 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
{
case 'b':
case 'B':
- my_strtobin(data, endptr+2, len_in_bits, 2, case_type, false);
+ my_strtobin(data, endptr+2, len_in_bits, 2, case_type, is_unsized);
break;
case 'o':
case 'O':
- my_strtobin(data, endptr+2, len_in_bits, 8, case_type, false);
+ my_strtobin(data, endptr+2, len_in_bits, 8, case_type, is_unsized);
break;
case 'd':
case 'D':
- my_strtobin(data, endptr+2, len_in_bits, 10, case_type, false);
+ my_strtobin(data, endptr+2, len_in_bits, 10, case_type, is_unsized);
break;
case 'h':
case 'H':
- my_strtobin(data, endptr+2, len_in_bits, 16, case_type, false);
+ my_strtobin(data, endptr+2, len_in_bits, 16, case_type, is_unsized);
break;
default:
char next_char = char(tolower(*(endptr+1)));
if (next_char == '0' || next_char == '1' || next_char == 'x' || next_char == 'z') {
- my_strtobin(data, endptr+1, 1, 2, case_type, true);
is_unsized = true;
+ my_strtobin(data, endptr+1, 1, 2, case_type, is_unsized);
} else {
return NULL;
}
}
if (len_in_bits < 0) {
- if (is_signed && data.back() == RTLIL::S1)
- data.push_back(RTLIL::S0);
+ if (is_signed && data.back() == State::S1)
+ data.push_back(State::S0);
}
return AstNode::mkconst_bits(data, is_signed, is_unsized);
}
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index d3fd91473..57e55b1f4 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -70,6 +70,9 @@ YOSYS_NAMESPACE_END
#define YY_INPUT(buf,result,max_size) \
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
+#undef YY_BUF_SIZE
+#define YY_BUF_SIZE 65536
+
%}
%option yylineno
@@ -193,6 +196,8 @@ YOSYS_NAMESPACE_END
to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
global state.. its a mess) */
[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
+ if (!strcmp(yytext, "default"))
+ return TOK_DEFAULT;
frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
return TOK_SVA_LABEL;
}
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 8234479cc..4afd72b73 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -274,7 +274,7 @@ hierarchical_id:
$$ = $1;
} |
hierarchical_id TOK_PACKAGESEP TOK_ID {
- if ($3->substr(0, 1) == "\\")
+ if ($3->compare(0, 1, "\\") == 0)
*$1 += "::" + $3->substr(1);
else
*$1 += "::" + *$3;
@@ -282,7 +282,7 @@ hierarchical_id:
$$ = $1;
} |
hierarchical_id '.' TOK_ID {
- if ($3->substr(0, 1) == "\\")
+ if ($3->compare(0, 1, "\\") == 0)
*$1 += "." + $3->substr(1);
else
*$1 += "." + *$3;
@@ -517,6 +517,7 @@ wire_type_token:
TOK_GENVAR {
astbuf3->type = AST_GENVAR;
astbuf3->is_reg = true;
+ astbuf3->is_signed = true;
astbuf3->range_left = 31;
astbuf3->range_right = 0;
} |
@@ -1020,13 +1021,8 @@ list_of_specparam_assignments:
specparam_assignment:
ignspec_id '=' constant_mintypmax_expression ;
-/*
-pulsestyle_declaration :
- ;
-
-showcancelled_declaration :
- ;
-*/
+ignspec_opt_cond:
+ TOK_IF '(' ignspec_expr ')' | /* empty */;
path_declaration :
simple_path_declaration ';'
@@ -1035,8 +1031,8 @@ path_declaration :
;
simple_path_declaration :
- parallel_path_description '=' path_delay_value |
- full_path_description '=' path_delay_value
+ ignspec_opt_cond parallel_path_description '=' path_delay_value |
+ ignspec_opt_cond full_path_description '=' path_delay_value
;
path_delay_value :
@@ -1046,32 +1042,20 @@ path_delay_value :
;
list_of_path_delay_extra_expressions :
-/*
- t_path_delay_expression
- | trise_path_delay_expression ',' tfall_path_delay_expression
- | trise_path_delay_expression ',' tfall_path_delay_expression ',' tz_path_delay_expression
- | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
- tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression
- | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
- tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression ','
- t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ','
- tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression
-*/
- ',' path_delay_expression
- | ',' path_delay_expression ',' path_delay_expression
- | ',' path_delay_expression ',' path_delay_expression ','
- path_delay_expression ',' path_delay_expression ',' path_delay_expression
- | ',' path_delay_expression ',' path_delay_expression ','
- path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
- path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
- path_delay_expression ',' path_delay_expression ',' path_delay_expression
- ;
+ ',' path_delay_expression | ',' path_delay_expression list_of_path_delay_extra_expressions;
+
+specify_edge_identifier :
+ TOK_POSEDGE | TOK_NEGEDGE ;
parallel_path_description :
- '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ;
+ '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' |
+ '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor opt_polarity_operator ':' ignspec_expr ')' ')' |
+ '(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor TOK_POS_INDEXED ignspec_expr ')' ')' ;
full_path_description :
- '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ;
+ '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' |
+ '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs opt_polarity_operator ':' ignspec_expr ')' ')' |
+ '(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs TOK_POS_INDEXED ignspec_expr ')' ')' ;
// This was broken into 2 rules to solve shift/reduce conflicts
list_of_path_inputs :
@@ -1111,56 +1095,6 @@ system_timing_args :
system_timing_arg |
system_timing_args ',' system_timing_arg ;
-/*
-t_path_delay_expression :
- path_delay_expression;
-
-trise_path_delay_expression :
- path_delay_expression;
-
-tfall_path_delay_expression :
- path_delay_expression;
-
-tz_path_delay_expression :
- path_delay_expression;
-
-t01_path_delay_expression :
- path_delay_expression;
-
-t10_path_delay_expression :
- path_delay_expression;
-
-t0z_path_delay_expression :
- path_delay_expression;
-
-tz1_path_delay_expression :
- path_delay_expression;
-
-t1z_path_delay_expression :
- path_delay_expression;
-
-tz0_path_delay_expression :
- path_delay_expression;
-
-t0x_path_delay_expression :
- path_delay_expression;
-
-tx1_path_delay_expression :
- path_delay_expression;
-
-t1x_path_delay_expression :
- path_delay_expression;
-
-tx0_path_delay_expression :
- path_delay_expression;
-
-txz_path_delay_expression :
- path_delay_expression;
-
-tzx_path_delay_expression :
- path_delay_expression;
-*/
-
path_delay_expression :
ignspec_constant_expression;
@@ -1400,7 +1334,13 @@ wire_name:
node->children.push_back(rng);
}
node->type = AST_MEMORY;
- node->children.push_back($2);
+ auto *rangeNode = $2;
+ 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));
+ }
+ node->children.push_back(rangeNode);
}
if (current_function_or_task == NULL) {
if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) {
@@ -2244,7 +2184,7 @@ basic_expr:
$$ = $1;
} |
'(' expr ')' TOK_CONSTVAL {
- if ($4->substr(0, 1) != "'")
+ if ($4->compare(0, 1, "'") != 0)
frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
AstNode *bits = $2;
AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
@@ -2254,7 +2194,7 @@ basic_expr:
delete $4;
} |
hierarchical_id TOK_CONSTVAL {
- if ($2->substr(0, 1) != "'")
+ if ($2->compare(0, 1, "'") != 0)
frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
AstNode *bits = new AstNode(AST_IDENTIFIER);
bits->str = *$1;