aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bitpattern.h10
-rw-r--r--kernel/calc.cc59
-rw-r--r--kernel/cellaigs.cc481
-rw-r--r--kernel/cellaigs.h52
-rw-r--r--kernel/celltypes.h67
-rw-r--r--kernel/consteval.h4
-rw-r--r--kernel/cost.h4
-rw-r--r--kernel/driver.cc90
-rw-r--r--kernel/hashlib.h241
-rw-r--r--kernel/log.cc55
-rw-r--r--kernel/log.h59
-rw-r--r--kernel/macc.h8
-rw-r--r--kernel/modtools.h31
-rw-r--r--kernel/register.cc148
-rw-r--r--kernel/register.h25
-rw-r--r--kernel/rtlil.cc372
-rw-r--r--kernel/rtlil.h104
-rw-r--r--kernel/satgen.h150
-rw-r--r--kernel/sigtools.h174
-rw-r--r--kernel/utils.h6
-rw-r--r--kernel/yosys.cc106
-rw-r--r--kernel/yosys.h37
22 files changed, 1884 insertions, 399 deletions
diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h
index 00bbc3bfb..894a95ed1 100644
--- a/kernel/bitpattern.h
+++ b/kernel/bitpattern.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -30,7 +30,7 @@ struct BitPatternPool
int width;
struct bits_t {
std::vector<RTLIL::State> bitdata;
- unsigned int cached_hash;
+ mutable unsigned int cached_hash;
bits_t(int width = 0) : bitdata(width), cached_hash(0) { }
RTLIL::State &operator[](int index) {
return bitdata[index];
@@ -45,7 +45,7 @@ struct BitPatternPool
}
unsigned int hash() const {
if (!cached_hash)
- ((bits_t*)this)->cached_hash = hash_ops<std::vector<RTLIL::State>>::hash(bitdata);
+ cached_hash = hash_ops<std::vector<RTLIL::State>>::hash(bitdata);
return cached_hash;
}
};
@@ -154,7 +154,7 @@ struct BitPatternPool
{
return database.empty();
}
-};
+};
YOSYS_NAMESPACE_END
diff --git a/kernel/calc.cc b/kernel/calc.cc
index aa3e8b919..a24fa2abf 100644
--- a/kernel/calc.cc
+++ b/kernel/calc.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -41,21 +41,28 @@ static void extend_u0(RTLIL::Const &arg, int width, bool is_signed)
static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos)
{
- BigInteger result = 0, this_bit = 1;
- for (size_t i = 0; i < val.bits.size(); i++) {
- if (val.bits[i] == RTLIL::State::S1) {
- if (as_signed && i+1 == val.bits.size())
- result -= this_bit;
- else
- result += this_bit;
- }
- else if (val.bits[i] != RTLIL::State::S0) {
- if (undef_bit_pos < 0)
- undef_bit_pos = i;
- }
- this_bit *= 2;
+ BigUnsigned mag;
+
+ BigInteger::Sign sign = BigInteger::positive;
+ State inv_sign_bit = RTLIL::State::S1;
+ size_t num_bits = val.bits.size();
+
+ if (as_signed && num_bits && val.bits[num_bits-1] == RTLIL::State::S1) {
+ inv_sign_bit = RTLIL::State::S0;
+ sign = BigInteger::negative;
+ num_bits--;
}
- return result;
+
+ for (size_t i = 0; i < num_bits; i++)
+ if (val.bits[i] == RTLIL::State::S0 || val.bits[i] == RTLIL::State::S1)
+ mag.setBit(i, val.bits[i] == inv_sign_bit);
+ else if (undef_bit_pos < 0)
+ undef_bit_pos = i;
+
+ if (sign == BigInteger::negative)
+ mag += 1;
+
+ return BigInteger(mag, sign);
}
static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_bit_pos)
@@ -147,7 +154,7 @@ static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL:
RTLIL::Const arg1, RTLIL::Const arg2, bool signed1, bool signed2, int result_len = -1)
{
if (result_len < 0)
- result_len = std::max(arg1.bits.size(), arg2.bits.size());
+ result_len = max(arg1.bits.size(), arg2.bits.size());
extend_u0(arg1, result_len, signed1);
extend_u0(arg2, result_len, signed2);
@@ -303,7 +310,7 @@ RTLIL::Const RTLIL::const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2
RTLIL::Const RTLIL::const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool, int result_len)
{
RTLIL::Const arg1_ext = arg1;
- extend_u0(arg1_ext, std::max(result_len, GetSize(arg1)), signed1);
+ extend_u0(arg1_ext, max(result_len, GetSize(arg1)), signed1);
return const_shift_worker(arg1_ext, arg2, false, +1, result_len);
}
@@ -382,7 +389,7 @@ RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
RTLIL::Const arg2_ext = arg2;
RTLIL::Const result(RTLIL::State::S0, result_len);
- int width = std::max(arg1_ext.bits.size(), arg2_ext.bits.size());
+ int width = max(arg1_ext.bits.size(), arg2_ext.bits.size());
extend_u0(arg1_ext, width, signed1 && signed2);
extend_u0(arg2_ext, width, signed1 && signed2);
@@ -416,7 +423,7 @@ RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2
RTLIL::Const arg2_ext = arg2;
RTLIL::Const result(RTLIL::State::S0, result_len);
- int width = std::max(arg1_ext.bits.size(), arg2_ext.bits.size());
+ int width = max(arg1_ext.bits.size(), arg2_ext.bits.size());
extend_u0(arg1_ext, width, signed1 && signed2);
extend_u0(arg2_ext, width, signed1 && signed2);
@@ -465,21 +472,21 @@ RTLIL::Const RTLIL::const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2
{
int undef_bit_pos = -1;
BigInteger y = const2big(arg1, signed1, undef_bit_pos) + const2big(arg2, signed2, undef_bit_pos);
- return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
+ return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
}
RTLIL::Const RTLIL::const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
{
int undef_bit_pos = -1;
BigInteger y = const2big(arg1, signed1, undef_bit_pos) - const2big(arg2, signed2, undef_bit_pos);
- return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
+ return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), undef_bit_pos);
}
RTLIL::Const RTLIL::const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
{
int undef_bit_pos = -1;
BigInteger y = const2big(arg1, signed1, undef_bit_pos) * const2big(arg2, signed2, undef_bit_pos);
- return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
+ return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
}
RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
@@ -492,7 +499,7 @@ RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2
bool result_neg = (a.getSign() == BigInteger::negative) != (b.getSign() == BigInteger::negative);
a = a.getSign() == BigInteger::negative ? -a : a;
b = b.getSign() == BigInteger::negative ? -b : b;
- return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
+ return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
}
RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
@@ -505,7 +512,7 @@ RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2
bool result_neg = a.getSign() == BigInteger::negative;
a = a.getSign() == BigInteger::negative ? -a : a;
b = b.getSign() == BigInteger::negative ? -b : b;
- return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
+ return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
}
RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
@@ -556,7 +563,7 @@ RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2
y *= -1;
}
- return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
+ return big2const(y, result_len >= 0 ? result_len : max(arg1.bits.size(), arg2.bits.size()), min(undef_bit_pos, 0));
}
RTLIL::Const RTLIL::const_pos(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc
new file mode 100644
index 000000000..41f81355d
--- /dev/null
+++ b/kernel/cellaigs.cc
@@ -0,0 +1,481 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+#include "kernel/cellaigs.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+AigNode::AigNode()
+{
+ portbit = -1;
+ inverter = false;
+ left_parent = -1;
+ right_parent = -1;
+}
+
+bool AigNode::operator==(const AigNode &other) const
+{
+ if (portname != other.portname) return false;
+ if (portbit != other.portbit) return false;
+ if (inverter != other.inverter) return false;
+ if (left_parent != other.left_parent) return false;
+ if (right_parent != other.right_parent) return false;
+ return true;
+}
+
+unsigned int AigNode::hash() const
+{
+ unsigned int h = mkhash_init;
+ h = mkhash(portname.hash(), portbit);
+ h = mkhash(h, inverter);
+ h = mkhash(h, left_parent);
+ h = mkhash(h, right_parent);
+ return h;
+}
+
+bool Aig::operator==(const Aig &other) const
+{
+ return name == other.name;
+}
+
+unsigned int Aig::hash() const
+{
+ return hash_ops<std::string>::hash(name);
+}
+
+struct AigMaker
+{
+ Aig *aig;
+ Cell *cell;
+ idict<AigNode> aig_indices;
+
+ int the_true_node;
+ int the_false_node;
+
+ AigMaker(Aig *aig, Cell *cell) : aig(aig), cell(cell)
+ {
+ the_true_node = -1;
+ the_false_node = -1;
+ }
+
+ int node2index(const AigNode &node)
+ {
+ if (node.left_parent > node.right_parent) {
+ AigNode n(node);
+ std::swap(n.left_parent, n.right_parent);
+ return node2index(n);
+ }
+
+ if (!aig_indices.count(node)) {
+ aig_indices.expect(node, GetSize(aig->nodes));
+ aig->nodes.push_back(node);
+ }
+
+ return aig_indices.at(node);
+ }
+
+ int bool_node(bool value)
+ {
+ AigNode node;
+ node.inverter = value;
+ return node2index(node);
+ }
+
+ int inport(IdString portname, int portbit = 0, bool inverter = false)
+ {
+ if (portbit >= GetSize(cell->getPort(portname))) {
+ if (cell->parameters.count(portname.str() + "_SIGNED") && cell->getParam(portname.str() + "_SIGNED").as_bool())
+ return inport(portname, GetSize(cell->getPort(portname))-1, inverter);
+ return bool_node(inverter);
+ }
+
+ AigNode node;
+ node.portname = portname;
+ node.portbit = portbit;
+ node.inverter = inverter;
+ return node2index(node);
+ }
+
+ vector<int> inport_vec(IdString portname, int width)
+ {
+ vector<int> vec;
+ for (int i = 0; i < width; i++)
+ vec.push_back(inport(portname, i));
+ return vec;
+ }
+
+ int not_inport(IdString portname, int portbit = 0)
+ {
+ return inport(portname, portbit, true);
+ }
+
+ int not_gate(int A)
+ {
+ AigNode node(aig_indices[A]);
+ node.outports.clear();
+ node.inverter = !node.inverter;
+ return node2index(node);
+ }
+
+ int and_gate(int A, int B, bool inverter = false)
+ {
+ if (A == B)
+ return inverter ? not_gate(A) : A;
+
+ const AigNode &nA = aig_indices[A];
+ const AigNode &nB = aig_indices[B];
+
+ AigNode nB_inv(nB);
+ nB_inv.inverter = !nB_inv.inverter;
+
+ if (nA == nB_inv)
+ return bool_node(inverter);
+
+ bool nA_bool = nA.portbit < 0 && nA.left_parent < 0 && nA.right_parent < 0;
+ bool nB_bool = nB.portbit < 0 && nB.left_parent < 0 && nB.right_parent < 0;
+
+ if (nA_bool && nB_bool) {
+ bool bA = nA.inverter;
+ bool bB = nB.inverter;
+ return bool_node(inverter != (bA && bB));
+ }
+
+ if (nA_bool) {
+ bool bA = nA.inverter;
+ if (inverter)
+ return bA ? not_gate(B) : bool_node(true);
+ return bA ? B : bool_node(false);
+ }
+
+ if (nB_bool) {
+ bool bB = nB.inverter;
+ if (inverter)
+ return bB ? not_gate(A) : bool_node(true);
+ return bB ? A : bool_node(false);
+ }
+
+ AigNode node;
+ node.inverter = inverter;
+ node.left_parent = A;
+ node.right_parent = B;
+ return node2index(node);
+ }
+
+ int nand_gate(int A, int B)
+ {
+ return and_gate(A, B, true);
+ }
+
+ int or_gate(int A, int B)
+ {
+ return nand_gate(not_gate(A), not_gate(B));
+ }
+
+ int nor_gate(int A, int B)
+ {
+ return and_gate(not_gate(A), not_gate(B));
+ }
+
+ int xor_gate(int A, int B)
+ {
+ return nor_gate(and_gate(A, B), nor_gate(A, B));
+ }
+
+ int xnor_gate(int A, int B)
+ {
+ return or_gate(and_gate(A, B), nor_gate(A, B));
+ }
+
+ int mux_gate(int A, int B, int S)
+ {
+ return or_gate(and_gate(A, not_gate(S)), and_gate(B, S));
+ }
+
+ vector<int> adder(const vector<int> &A, const vector<int> &B, int carry, vector<int> *X = nullptr, vector<int> *CO = nullptr)
+ {
+ vector<int> Y(GetSize(A));
+ log_assert(GetSize(A) == GetSize(B));
+ for (int i = 0; i < GetSize(A); i++) {
+ Y[i] = xor_gate(xor_gate(A[i], B[i]), carry);
+ carry = or_gate(and_gate(A[i], B[i]), and_gate(or_gate(A[i], B[i]), carry));
+ if (X != nullptr)
+ X->at(i) = xor_gate(A[i], B[i]);
+ if (CO != nullptr)
+ CO->at(i) = carry;
+ }
+ return Y;
+ }
+
+ void outport(int node, IdString portname, int portbit = 0)
+ {
+ if (portbit < GetSize(cell->getPort(portname)))
+ aig->nodes.at(node).outports.push_back(pair<IdString, int>(portname, portbit));
+ }
+
+ void outport_bool(int node, IdString portname)
+ {
+ outport(node, portname);
+ for (int i = 1; i < GetSize(cell->getPort(portname)); i++)
+ outport(bool_node(false), portname, i);
+ }
+
+ void outport_vec(const vector<int> &vec, IdString portname)
+ {
+ for (int i = 0; i < GetSize(vec); i++)
+ outport(vec.at(i), portname, i);
+ }
+};
+
+Aig::Aig(Cell *cell)
+{
+ if (cell->type[0] != '$')
+ return;
+
+ AigMaker mk(this, cell);
+ name = cell->type.str();
+
+ string mkname_last;
+ bool mkname_a_signed = false;
+ bool mkname_b_signed = false;
+ bool mkname_is_signed = false;
+
+ cell->parameters.sort();
+ for (auto p : cell->parameters)
+ {
+ if (p.first == "\\A_WIDTH" && mkname_a_signed) {
+ name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
+ } else if (p.first == "\\B_WIDTH" && mkname_b_signed) {
+ name = mkname_last + stringf(":%d%c", p.second.as_int(), mkname_is_signed ? 'S' : 'U');
+ } else {
+ mkname_last = name;
+ name += stringf(":%d", p.second.as_int());
+ }
+
+ mkname_a_signed = false;
+ mkname_b_signed = false;
+ mkname_is_signed = false;
+ if (p.first == "\\A_SIGNED") {
+ mkname_a_signed = true;
+ mkname_is_signed = p.second.as_bool();
+ }
+ if (p.first == "\\B_SIGNED") {
+ mkname_b_signed = true;
+ mkname_is_signed = p.second.as_bool();
+ }
+ }
+
+ if (cell->type.in("$not", "$_NOT_", "$pos", "$_BUF_"))
+ {
+ for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
+ int A = mk.inport("\\A", i);
+ int Y = cell->type.in("$not", "$_NOT_") ? mk.not_gate(A) : A;
+ mk.outport(Y, "\\Y", i);
+ }
+ goto optimize;
+ }
+
+ if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$xor", "$xnor", "$_XOR_", "$_XNOR_"))
+ {
+ for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
+ int A = mk.inport("\\A", i);
+ int B = mk.inport("\\B", i);
+ int Y = cell->type.in("$and", "$_AND_") ? mk.and_gate(A, B) :
+ cell->type.in("$_NAND_") ? mk.nand_gate(A, B) :
+ cell->type.in("$or", "$_OR_") ? mk.or_gate(A, B) :
+ cell->type.in("$_NOR_") ? mk.nor_gate(A, B) :
+ cell->type.in("$xor", "$_XOR_") ? mk.xor_gate(A, B) :
+ cell->type.in("$xnor", "$_XNOR_") ? mk.xnor_gate(A, B) : -1;
+ mk.outport(Y, "\\Y", i);
+ }
+ goto optimize;
+ }
+
+ if (cell->type.in("$mux", "$_MUX_"))
+ {
+ int S = mk.inport("\\S");
+ for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) {
+ int A = mk.inport("\\A", i);
+ int B = mk.inport("\\B", i);
+ int Y = mk.mux_gate(A, B, S);
+ mk.outport(Y, "\\Y", i);
+ }
+ goto optimize;
+ }
+
+ if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool"))
+ {
+ int Y = mk.inport("\\A", 0);
+ for (int i = 1; i < GetSize(cell->getPort("\\A")); i++) {
+ int A = mk.inport("\\A", i);
+ if (cell->type == "$reduce_and") Y = mk.and_gate(A, Y);
+ if (cell->type == "$reduce_or") Y = mk.or_gate(A, Y);
+ if (cell->type == "$reduce_bool") Y = mk.or_gate(A, Y);
+ if (cell->type == "$reduce_xor") Y = mk.xor_gate(A, Y);
+ if (cell->type == "$reduce_xnor") Y = mk.xor_gate(A, Y);
+ }
+ if (cell->type == "$reduce_xnor")
+ Y = mk.not_gate(Y);
+ mk.outport(Y, "\\Y", 0);
+ for (int i = 1; i < GetSize(cell->getPort("\\Y")); i++)
+ mk.outport(mk.bool_node(false), "\\Y", i);
+ goto optimize;
+ }
+
+ if (cell->type.in("$logic_not", "$logic_and", "$logic_or"))
+ {
+ int A = mk.inport("\\A", 0), Y = -1;
+ for (int i = 1; i < GetSize(cell->getPort("\\A")); i++)
+ A = mk.or_gate(mk.inport("\\A", i), A);
+ if (cell->type.in("$logic_and", "$logic_or")) {
+ int B = mk.inport("\\B", 0);
+ for (int i = 1; i < GetSize(cell->getPort("\\B")); i++)
+ B = mk.or_gate(mk.inport("\\B", i), B);
+ if (cell->type == "$logic_and") Y = mk.and_gate(A, B);
+ if (cell->type == "$logic_or") Y = mk.or_gate(A, B);
+ } else {
+ if (cell->type == "$logic_not") Y = mk.not_gate(A);
+ }
+ mk.outport_bool(Y, "\\Y");
+ goto optimize;
+ }
+
+ if (cell->type.in("$add", "$sub"))
+ {
+ int width = GetSize(cell->getPort("\\Y"));
+ vector<int> A = mk.inport_vec("\\A", width);
+ vector<int> B = mk.inport_vec("\\B", width);
+ int carry = mk.bool_node(false);
+ if (cell->type == "$sub") {
+ for (auto &n : B)
+ n = mk.not_gate(n);
+ carry = mk.not_gate(carry);
+ }
+ vector<int> Y = mk.adder(A, B, carry);
+ mk.outport_vec(Y, "\\Y");
+ goto optimize;
+ }
+
+ if (cell->type == "$alu")
+ {
+ int width = GetSize(cell->getPort("\\Y"));
+ vector<int> A = mk.inport_vec("\\A", width);
+ vector<int> B = mk.inport_vec("\\B", width);
+ int carry = mk.inport("\\CI");
+ int binv = mk.inport("\\BI");
+ for (auto &n : B)
+ n = mk.xor_gate(n, binv);
+ vector<int> X(width), CO(width);
+ vector<int> Y = mk.adder(A, B, carry, &X, &CO);
+ for (int i = 0; i < width; i++)
+ X[i] = mk.xor_gate(A[i], B[i]);
+ mk.outport_vec(Y, "\\Y");
+ mk.outport_vec(X, "\\X");
+ mk.outport_vec(CO, "\\CO");
+ goto optimize;
+ }
+
+ if (cell->type.in("$eq", "$ne"))
+ {
+ int width = max(GetSize(cell->getPort("\\A")), GetSize(cell->getPort("\\B")));
+ vector<int> A = mk.inport_vec("\\A", width);
+ vector<int> B = mk.inport_vec("\\B", width);
+ int Y = mk.bool_node(false);
+ for (int i = 0; i < width; i++)
+ Y = mk.or_gate(Y, mk.xor_gate(A[i], B[i]));
+ if (cell->type == "$eq")
+ Y = mk.not_gate(Y);
+ mk.outport_bool(Y, "\\Y");
+ goto optimize;
+ }
+
+ if (cell->type == "$_AOI3_")
+ {
+ int A = mk.inport("\\A");
+ int B = mk.inport("\\B");
+ int C = mk.inport("\\C");
+ int Y = mk.nor_gate(mk.and_gate(A, B), C);
+ mk.outport(Y, "\\Y");
+ goto optimize;
+ }
+
+ if (cell->type == "$_OAI3_")
+ {
+ int A = mk.inport("\\A");
+ int B = mk.inport("\\B");
+ int C = mk.inport("\\C");
+ int Y = mk.nand_gate(mk.or_gate(A, B), C);
+ mk.outport(Y, "\\Y");
+ goto optimize;
+ }
+
+ if (cell->type == "$_AOI4_")
+ {
+ int A = mk.inport("\\A");
+ int B = mk.inport("\\B");
+ int C = mk.inport("\\C");
+ int D = mk.inport("\\D");
+ int Y = mk.nor_gate(mk.and_gate(A, B), mk.and_gate(C, D));
+ mk.outport(Y, "\\Y");
+ goto optimize;
+ }
+
+ if (cell->type == "$_OAI4_")
+ {
+ int A = mk.inport("\\A");
+ int B = mk.inport("\\B");
+ int C = mk.inport("\\C");
+ int D = mk.inport("\\D");
+ int Y = mk.nand_gate(mk.nor_gate(A, B), mk.nor_gate(C, D));
+ mk.outport(Y, "\\Y");
+ goto optimize;
+ }
+
+ name.clear();
+ return;
+
+optimize:;
+ pool<int> used_old_ids;
+ vector<AigNode> new_nodes;
+ dict<int, int> old_to_new_ids;
+ old_to_new_ids[-1] = -1;
+
+ for (int i = GetSize(nodes)-1; i >= 0; i--) {
+ if (!nodes[i].outports.empty())
+ used_old_ids.insert(i);
+ if (!used_old_ids.count(i))
+ continue;
+ if (nodes[i].left_parent >= 0)
+ used_old_ids.insert(nodes[i].left_parent);
+ if (nodes[i].right_parent >= 0)
+ used_old_ids.insert(nodes[i].right_parent);
+ }
+
+ for (int i = 0; i < GetSize(nodes); i++) {
+ if (!used_old_ids.count(i))
+ continue;
+ nodes[i].left_parent = old_to_new_ids.at(nodes[i].left_parent);
+ nodes[i].right_parent = old_to_new_ids.at(nodes[i].right_parent);
+ old_to_new_ids[i] = GetSize(new_nodes);
+ new_nodes.push_back(nodes[i]);
+ }
+
+ new_nodes.swap(nodes);
+}
+
+YOSYS_NAMESPACE_END
diff --git a/kernel/cellaigs.h b/kernel/cellaigs.h
new file mode 100644
index 000000000..1417a614c
--- /dev/null
+++ b/kernel/cellaigs.h
@@ -0,0 +1,52 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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.
+ *
+ */
+
+#ifndef CELLAIGS_H
+#define CELLAIGS_H
+
+#include "kernel/yosys.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+struct AigNode
+{
+ IdString portname;
+ int portbit;
+ bool inverter;
+ int left_parent, right_parent;
+ vector<pair<IdString, int>> outports;
+
+ AigNode();
+ bool operator==(const AigNode &other) const;
+ unsigned int hash() const;
+};
+
+struct Aig
+{
+ string name;
+ vector<AigNode> nodes;
+ Aig(Cell *cell);
+
+ bool operator==(const Aig &other) const;
+ unsigned int hash() const;
+};
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index 60e6606f8..cf7bc2dcf 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -85,7 +85,7 @@ struct CellTypes
std::vector<RTLIL::IdString> unary_ops = {
"$not", "$pos", "$neg",
"$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
- "$logic_not", "$slice", "$lut"
+ "$logic_not", "$slice", "$lut", "$sop"
};
std::vector<RTLIL::IdString> binary_ops = {
@@ -95,7 +95,6 @@ struct CellTypes
"$add", "$sub", "$mul", "$div", "$mod", "$pow",
"$logic_and", "$logic_or", "$concat", "$macc"
};
-
IdString A = "\\A", B = "\\B", S = "\\S", Y = "\\Y";
IdString P = "\\P", G = "\\G", C = "\\C", X = "\\X";
IdString BI = "\\BI", CI = "\\CI", CO = "\\CO", EN = "\\EN";
@@ -113,14 +112,17 @@ struct CellTypes
setup_type("$alu", {A, B, CI, BI}, {X, Y, CO}, true);
setup_type("$fa", {A, B, C}, {X, Y}, true);
+ setup_type("$tribuf", {A, EN}, {Y}, true);
+
setup_type("$assert", {A, EN}, pool<RTLIL::IdString>(), true);
+ setup_type("$assume", {A, EN}, pool<RTLIL::IdString>(), true);
setup_type("$equiv", {A, B}, {Y}, true);
}
void setup_internals_mem()
{
IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
- IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA";
+ IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA", RD_EN = "\\RD_EN";
IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN";
IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA";
IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT";
@@ -133,16 +135,23 @@ struct CellTypes
setup_type("$dlatch", {EN, D}, {Q});
setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q});
- setup_type("$memrd", {CLK, ADDR}, {DATA});
+ setup_type("$memrd", {CLK, EN, ADDR}, {DATA});
setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
- setup_type("$mem", {RD_CLK, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
+ setup_type("$meminit", {ADDR, DATA}, pool<RTLIL::IdString>());
+ setup_type("$mem", {RD_CLK, RD_EN, RD_ADDR, WR_CLK, WR_EN, WR_ADDR, WR_DATA}, {RD_DATA});
setup_type("$fsm", {CLK, ARST, CTRL_IN}, {CTRL_OUT});
}
void setup_stdcells()
{
- IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D", S = "\\S", Y = "\\Y";
+ IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D";
+ IdString E = "\\E", F = "\\F", G = "\\G", H = "\\H";
+ IdString I = "\\I", J = "\\J", K = "\\K", L = "\\L";
+ IdString M = "\\I", N = "\\N", O = "\\O", P = "\\P";
+ IdString S = "\\S", T = "\\T", U = "\\U", V = "\\V";
+ IdString Y = "\\Y";
+
setup_type("$_BUF_", {A}, {Y}, true);
setup_type("$_NOT_", {A}, {Y}, true);
setup_type("$_AND_", {A, B}, {Y}, true);
@@ -152,10 +161,14 @@ struct CellTypes
setup_type("$_XOR_", {A, B}, {Y}, true);
setup_type("$_XNOR_", {A, B}, {Y}, true);
setup_type("$_MUX_", {A, B, S}, {Y}, true);
+ setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true);
+ setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
+ setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);
setup_type("$_AOI3_", {A, B, C}, {Y}, true);
setup_type("$_OAI3_", {A, B, C}, {Y}, true);
setup_type("$_AOI4_", {A, B, C, D}, {Y}, true);
setup_type("$_OAI4_", {A, B, C, D}, {Y}, true);
+ setup_type("$_TBUF_", {A, E}, {Y}, true);
}
void setup_stdcells_mem()
@@ -344,6 +357,44 @@ struct CellTypes
return t;
}
+ if (cell->type == "$sop")
+ {
+ int width = cell->parameters.at("\\WIDTH").as_int();
+ int depth = cell->parameters.at("\\DEPTH").as_int();
+ std::vector<RTLIL::State> t = cell->parameters.at("\\TABLE").bits;
+
+ while (GetSize(t) < width*depth*2)
+ t.push_back(RTLIL::S0);
+
+ RTLIL::State default_ret = State::S0;
+
+ for (int i = 0; i < depth; i++)
+ {
+ bool match = true;
+ bool match_x = true;
+
+ for (int j = 0; j < width; j++) {
+ RTLIL::State a = arg1.bits.at(j);
+ if (t.at(2*width*i + 2*j + 0) == State::S1) {
+ if (a == State::S1) match_x = false;
+ if (a != State::S0) match = false;
+ }
+ if (t.at(2*width*i + 2*j + 1) == State::S1) {
+ if (a == State::S0) match_x = false;
+ if (a != State::S1) match = false;
+ }
+ }
+
+ if (match)
+ return State::S1;
+
+ if (match_x)
+ default_ret = State::Sx;
+ }
+
+ return default_ret;
+ }
+
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
diff --git a/kernel/consteval.h b/kernel/consteval.h
index c2e9710fb..4d48b45ea 100644
--- a/kernel/consteval.h
+++ b/kernel/consteval.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
diff --git a/kernel/cost.h b/kernel/cost.h
index c6c631e0a..4f12889f4 100644
--- a/kernel/cost.h
+++ b/kernel/cost.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
diff --git a/kernel/driver.cc b/kernel/driver.cc
index 116df542c..45cdd461d 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -72,6 +72,53 @@ int getopt(int argc, char **argv, const char *optstring)
USING_YOSYS_NAMESPACE
+#ifdef EMSCRIPTEN
+# include <sys/stat.h>
+# include <sys/types.h>
+
+extern "C" int main(int, char**);
+extern "C" void run(const char*);
+extern "C" const char *errmsg();
+extern "C" const char *prompt();
+
+int main(int, char**)
+{
+ mkdir("/work", 0777);
+ chdir("/work");
+ log_files.push_back(stdout);
+ log_error_stderr = true;
+ yosys_banner();
+ yosys_setup();
+}
+
+void run(const char *command)
+{
+ int selSize = GetSize(yosys_get_design()->selection_stack);
+ try {
+ log_last_error = "Internal error (see JavaScript console for details)";
+ run_pass(command);
+ log_last_error = "";
+ } catch (...) {
+ while (GetSize(yosys_get_design()->selection_stack) > selSize)
+ yosys_get_design()->selection_stack.pop_back();
+ throw;
+ }
+}
+
+const char *errmsg()
+{
+ return log_last_error.c_str();
+}
+
+const char *prompt()
+{
+ const char *p = create_prompt(yosys_get_design(), 0);
+ while (*p == '\n') p++;
+ return p;
+}
+
+#else /* EMSCRIPTEN */
+
int main(int argc, char **argv)
{
std::string frontend_command = "auto";
@@ -136,8 +183,8 @@ int main(int argc, char **argv)
printf(" -b backend\n");
printf(" use this backend for the output file specified on the command line\n");
printf("\n");
- printf(" -f backend\n");
- printf(" use the specified front for the input files on the command line\n");
+ printf(" -f frontend\n");
+ printf(" use the specified frontend for the input files on the command line\n");
printf("\n");
printf(" -H\n");
printf(" print the command list\n");
@@ -166,11 +213,16 @@ int main(int argc, char **argv)
printf(" -A\n");
printf(" will call abort() at the end of the script. for debugging\n");
printf("\n");
+ printf(" -D <header_id>[:<filename>]\n");
+ printf(" dump the design when printing the specified log header to a file.\n");
+ printf(" yosys_dump_<header_id>.il is used as filename if none is specified.\n");
+ printf(" Use 'ALL' as <header_id> to dump at every header.\n");
+ printf("\n");
printf(" -V\n");
printf(" print version information and exit\n");
printf("\n");
printf("The option -S is an shortcut for calling the \"synth\" command, a default\n");
- printf("script for transforming the verilog input to a gate-level netlist. For example:\n");
+ printf("script for transforming the Verilog input to a gate-level netlist. For example:\n");
printf("\n");
printf(" yosys -o output.blif -S input.v\n");
printf("\n");
@@ -186,7 +238,7 @@ int main(int argc, char **argv)
}
int opt;
- while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:")) != -1)
+ while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:D:")) != -1)
{
switch (opt)
{
@@ -268,6 +320,28 @@ int main(int argc, char **argv)
scriptfile = optarg;
scriptfile_tcl = true;
break;
+ case 'D':
+ {
+ auto args = split_tokens(optarg, ":");
+ if (!args.empty() && args[0] == "ALL") {
+ if (GetSize(args) != 1) {
+ fprintf(stderr, "Invalid number of tokens in -D ALL.\n");
+ exit(1);
+ }
+ log_hdump_all = true;
+ } else {
+ if (!args.empty() && !args[0].empty() && args[0].back() == '.')
+ args[0].pop_back();
+ if (GetSize(args) == 1)
+ args.push_back("yosys_dump_" + args[0] + ".il");
+ if (GetSize(args) != 2) {
+ fprintf(stderr, "Invalid number of tokens in -D.\n");
+ exit(1);
+ }
+ log_hdump[args[0]].insert(args[1]);
+ }
+ }
+ break;
default:
fprintf(stderr, "Run '%s -h' for help.\n", argv[0]);
exit(1);
@@ -357,7 +431,7 @@ int main(int argc, char **argv)
log("%s\n", yosys_version_str);
int64_t total_ns = 0;
- std::set<std::tuple<int64_t, int, std::string>> timedat;
+ std::set<tuple<int64_t, int, std::string>> timedat;
for (auto &it : pass_register)
if (it.second->call_counter) {
@@ -440,3 +514,5 @@ int main(int argc, char **argv)
return 0;
}
+#endif /* EMSCRIPTEN */
+
diff --git a/kernel/hashlib.h b/kernel/hashlib.h
index c96023920..3c824b8c3 100644
--- a/kernel/hashlib.h
+++ b/kernel/hashlib.h
@@ -1,5 +1,5 @@
// This is free and unencumbered software released into the public domain.
-//
+//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
@@ -10,6 +10,7 @@
// -------------------------------------------------------
#ifndef HASHLIB_H
+#define HASHLIB_H
#include <stdexcept>
#include <algorithm>
@@ -30,7 +31,7 @@ inline unsigned int mkhash(unsigned int a, unsigned int b) {
const unsigned int mkhash_init = 5381;
// The ADD version of DJB2
-// (usunsigned int mkhashe this version for cache locality in b)
+// (use this version for cache locality in b)
inline unsigned int mkhash_add(unsigned int a, unsigned int b) {
return ((a << 5) + a) + b;
}
@@ -58,16 +59,25 @@ template<typename T> struct hash_ops {
}
};
-template<> struct hash_ops<int> {
+struct hash_int_ops {
template<typename T>
static inline bool cmp(T a, T b) {
return a == b;
}
- template<typename T>
- static inline unsigned int hash(T a) {
+};
+
+template<> struct hash_ops<int32_t> : hash_int_ops
+{
+ static inline unsigned int hash(int32_t a) {
return a;
}
};
+template<> struct hash_ops<int64_t> : hash_int_ops
+{
+ static inline unsigned int hash(int64_t a) {
+ return mkhash((unsigned int)(a), (unsigned int)(a >> 32));
+ }
+};
template<> struct hash_ops<std::string> {
static inline bool cmp(const std::string &a, const std::string &b) {
@@ -86,9 +96,22 @@ template<typename P, typename Q> struct hash_ops<std::pair<P, Q>> {
return a == b;
}
static inline unsigned int hash(std::pair<P, Q> a) {
- hash_ops<P> p_ops;
- hash_ops<Q> q_ops;
- return mkhash(p_ops.hash(a.first), q_ops.hash(a.second));
+ return mkhash(hash_ops<P>::hash(a.first), hash_ops<Q>::hash(a.second));
+ }
+};
+
+template<typename... T> struct hash_ops<std::tuple<T...>> {
+ static inline bool cmp(std::tuple<T...> a, std::tuple<T...> b) {
+ return a == b;
+ }
+ template<size_t I = 0>
+ static inline typename std::enable_if<I == sizeof...(T), unsigned int>::type hash(std::tuple<T...>) {
+ return mkhash_init;
+ }
+ template<size_t I = 0>
+ static inline typename std::enable_if<I != sizeof...(T), unsigned int>::type hash(std::tuple<T...> a) {
+ typedef hash_ops<typename std::tuple_element<I, std::tuple<T...>>::type> element_ops_t;
+ return mkhash(hash<I+1>(a), element_ops_t::hash(std::get<I>(a)));
}
};
@@ -97,10 +120,9 @@ template<typename T> struct hash_ops<std::vector<T>> {
return a == b;
}
static inline unsigned int hash(std::vector<T> a) {
- hash_ops<T> t_ops;
unsigned int h = mkhash_init;
for (auto k : a)
- h = mkhash(h, t_ops.hash(k));
+ h = mkhash(h, hash_ops<T>::hash(k));
return h;
}
};
@@ -115,8 +137,8 @@ struct hash_cstr_ops {
static inline unsigned int hash(const char *a) {
unsigned int hash = mkhash_init;
while (*a)
- hash = mkhash(hash, *(a++));
- return hash;
+ hash = mkhash(hash, *(a++));
+ return hash;
}
};
@@ -135,10 +157,15 @@ struct hash_obj_ops {
}
template<typename T>
static inline unsigned int hash(const T *a) {
- return a->hash();
+ return a ? a->hash() : 0;
}
};
+template<typename T>
+inline unsigned int mkhash(const T &v) {
+ return hash_ops<T>().hash(v);
+}
+
inline int hashtable_size(int min_size)
{
static std::vector<int> zero_and_some_primes = {
@@ -167,6 +194,7 @@ inline int hashtable_size(int min_size)
template<typename K, typename T, typename OPS = hash_ops<K>> class dict;
template<typename K, int offset = 0, typename OPS = hash_ops<K>> class idict;
template<typename K, typename OPS = hash_ops<K>> class pool;
+template<typename K, typename OPS = hash_ops<K>> class mfp;
template<typename K, typename T, typename OPS>
class dict
@@ -178,18 +206,19 @@ class dict
entry_t() { }
entry_t(const std::pair<K, T> &udata, int next) : udata(udata), next(next) { }
+ entry_t(std::pair<K, T> &&udata, int next) : udata(std::move(udata)), next(next) { }
};
std::vector<int> hashtable;
std::vector<entry_t> entries;
OPS ops;
-#if 0
+#ifdef NDEBUG
+ static inline void do_assert(bool) { }
+#else
static inline void do_assert(bool cond) {
if (!cond) throw std::runtime_error("dict<> assert failed.");
}
-#else
- static inline void do_assert(bool) { }
#endif
int do_hash(const K &key) const
@@ -203,7 +232,7 @@ class dict
void do_rehash()
{
hashtable.clear();
- hashtable.resize(hashtable_size(entries.size() * hashtable_size_factor), -1);
+ hashtable.resize(hashtable_size(entries.capacity() * hashtable_size_factor), -1);
for (int i = 0; i < int(entries.size()); i++) {
do_assert(-1 <= entries[i].next && entries[i].next < int(entries.size()));
@@ -220,6 +249,8 @@ class dict
return 0;
int k = hashtable[hash];
+ do_assert(0 <= k && k < int(entries.size()));
+
if (k == index) {
hashtable[hash] = entries[index].next;
} else {
@@ -237,6 +268,8 @@ class dict
int back_hash = do_hash(entries[back_idx].udata.first);
k = hashtable[back_hash];
+ do_assert(0 <= k && k < int(entries.size()));
+
if (k == back_idx) {
hashtable[back_hash] = index;
} else {
@@ -278,6 +311,19 @@ class dict
return index;
}
+ int do_insert(const K &key, int &hash)
+ {
+ if (hashtable.empty()) {
+ entries.push_back(entry_t(std::pair<K, T>(key, T()), -1));
+ do_rehash();
+ hash = do_hash(key);
+ } else {
+ entries.push_back(entry_t(std::pair<K, T>(key, T()), hashtable[hash]));
+ hashtable[hash] = entries.size() - 1;
+ }
+ return entries.size() - 1;
+ }
+
int do_insert(const std::pair<K, T> &value, int &hash)
{
if (hashtable.empty()) {
@@ -375,6 +421,16 @@ public:
insert(*first);
}
+ std::pair<iterator, bool> insert(const K &key)
+ {
+ int hash = do_hash(key);
+ int i = do_lookup(key, hash);
+ if (i >= 0)
+ return std::pair<iterator, bool>(iterator(this, i), false);
+ i = do_insert(key, hash);
+ return std::pair<iterator, bool>(iterator(this, i), true);
+ }
+
std::pair<iterator, bool> insert(const std::pair<K, T> &value)
{
int hash = do_hash(value.first);
@@ -449,6 +505,15 @@ public:
return entries[i].udata.second;
}
+ T at(const K &key, const T &defval) const
+ {
+ int hash = do_hash(key);
+ int i = do_lookup(key, hash);
+ if (i < 0)
+ return defval;
+ return entries[i].udata.second;
+ }
+
T& operator[](const K &key)
{
int hash = do_hash(key);
@@ -476,16 +541,17 @@ public:
return false;
for (auto &it : entries) {
auto oit = other.find(it.udata.first);
- if (oit == other.end() || oit->second != it.udata.second)
+ if (oit == other.end() || !(oit->second == it.udata.second))
return false;
}
return true;
}
bool operator!=(const dict &other) const {
- return !(*this == other);
+ return !operator==(other);
}
+ void reserve(size_t n) { entries.reserve(n); }
size_t size() const { return entries.size(); }
bool empty() const { return entries.empty(); }
void clear() { hashtable.clear(); entries.clear(); }
@@ -516,12 +582,12 @@ protected:
std::vector<entry_t> entries;
OPS ops;
-#if 0
+#ifdef NDEBUG
+ static inline void do_assert(bool) { }
+#else
static inline void do_assert(bool cond) {
if (!cond) throw std::runtime_error("pool<> assert failed.");
}
-#else
- static inline void do_assert(bool) { }
#endif
int do_hash(const K &key) const
@@ -535,7 +601,7 @@ protected:
void do_rehash()
{
hashtable.clear();
- hashtable.resize(hashtable_size(entries.size() * hashtable_size_factor), -1);
+ hashtable.resize(hashtable_size(entries.capacity() * hashtable_size_factor), -1);
for (int i = 0; i < int(entries.size()); i++) {
do_assert(-1 <= entries[i].next && entries[i].next < int(entries.size()));
@@ -775,6 +841,14 @@ public:
do_rehash();
}
+ K pop()
+ {
+ iterator it = begin();
+ K ret = *it;
+ erase(it);
+ return ret;
+ }
+
void swap(pool &other)
{
hashtable.swap(other.hashtable);
@@ -791,9 +865,10 @@ public:
}
bool operator!=(const pool &other) const {
- return !(*this == other);
+ return !operator==(other);
}
+ void reserve(size_t n) { entries.reserve(n); }
size_t size() const { return entries.size(); }
bool empty() const { return entries.empty(); }
void clear() { hashtable.clear(); entries.clear(); }
@@ -831,6 +906,15 @@ public:
return i + offset;
}
+ int at(const K &key, int defval) const
+ {
+ int hash = database.do_hash(key);
+ int i = database.do_lookup(key, hash);
+ if (i < 0)
+ return defval;
+ return i + offset;
+ }
+
int count(const K &key) const
{
int hash = database.do_hash(key);
@@ -850,6 +934,115 @@ public:
return database.entries.at(index - offset).udata;
}
+ void swap(idict &other)
+ {
+ database.swap(other.database);
+ }
+
+ void reserve(size_t n) { database.reserve(n); }
+ size_t size() const { return database.size(); }
+ bool empty() const { return database.empty(); }
+ void clear() { database.clear(); }
+
+ const_iterator begin() const { return database.begin(); }
+ const_iterator end() const { return database.end(); }
+};
+
+template<typename K, typename OPS>
+class mfp
+{
+ mutable idict<K, 0, OPS> database;
+ mutable std::vector<int> parents;
+
+public:
+ typedef typename idict<K, 0, OPS>::const_iterator const_iterator;
+
+ int operator()(const K &key) const
+ {
+ int i = database(key);
+ parents.resize(database.size(), -1);
+ return i;
+ }
+
+ const K &operator[](int index) const
+ {
+ return database[index];
+ }
+
+ int ifind(int i) const
+ {
+ int p = i, k = i;
+
+ while (parents[p] != -1)
+ p = parents[p];
+
+ while (k != p) {
+ int next_k = parents[k];
+ parents[k] = p;
+ k = next_k;
+ }
+
+ return p;
+ }
+
+ void imerge(int i, int j)
+ {
+ i = ifind(i);
+ j = ifind(j);
+
+ if (i != j)
+ parents[i] = j;
+ }
+
+ void ipromote(int i)
+ {
+ int k = i;
+
+ while (k != -1) {
+ int next_k = parents[k];
+ parents[k] = i;
+ k = next_k;
+ }
+
+ parents[i] = -1;
+ }
+
+ int lookup(const K &a) const
+ {
+ return ifind((*this)(a));
+ }
+
+ const K &find(const K &a) const
+ {
+ int i = database.at(a, -1);
+ if (i < 0)
+ return a;
+ return (*this)[ifind(i)];
+ }
+
+ void merge(const K &a, const K &b)
+ {
+ imerge((*this)(a), (*this)(b));
+ }
+
+ void promote(const K &a)
+ {
+ int i = database.at(a, -1);
+ if (i >= 0)
+ ipromote(i);
+ }
+
+ void swap(mfp &other)
+ {
+ database.swap(other.database);
+ parents.swap(other.parents);
+ }
+
+ void reserve(size_t n) { database.reserve(n); }
+ size_t size() const { return database.size(); }
+ bool empty() const { return database.empty(); }
+ void clear() { database.clear(); parents.clear(); }
+
const_iterator begin() const { return database.begin(); }
const_iterator end() const { return database.end(); }
};
diff --git a/kernel/log.cc b/kernel/log.cc
index ada2cabb2..fe84184a5 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -40,6 +40,8 @@ YOSYS_NAMESPACE_BEGIN
std::vector<FILE*> log_files;
std::vector<std::ostream*> log_streams;
+std::map<std::string, std::set<std::string>> log_hdump;
+bool log_hdump_all = false;
FILE *log_errfile = NULL;
SHA1 *log_hasher = NULL;
@@ -48,10 +50,11 @@ bool log_error_stderr = false;
bool log_cmd_error_throw = false;
bool log_quiet_warnings = false;
int log_verbose_level;
+string log_last_error;
vector<int> header_count;
pool<RTLIL::IdString> log_id_cache;
-vector<string> string_buf;
+vector<shared_str> string_buf;
int string_buf_index = -1;
static struct timeval initial_tv = { 0, 0 };
@@ -135,7 +138,7 @@ void logv(const char *format, va_list ap)
*f << str;
}
-void logv_header(const char *format, va_list ap)
+void logv_header(RTLIL::Design *design, const char *format, va_list ap)
{
bool pop_errfile = false;
@@ -148,12 +151,24 @@ void logv_header(const char *format, va_list ap)
pop_errfile = true;
}
+ std::string header_id;
+
for (int c : header_count)
- log("%d.", c);
- log(" ");
+ header_id += stringf("%s%d", header_id.empty() ? "" : ".", c);
+
+ log("%s. ", header_id.c_str());
logv(format, ap);
log_flush();
+ if (log_hdump_all)
+ log_hdump[header_id].insert("yosys_dump_" + header_id + ".il");
+
+ if (log_hdump.count(header_id) && design != nullptr)
+ for (auto &filename : log_hdump.at(header_id)) {
+ log("Dumping current design to '%s'.\n", filename.c_str());
+ Pass::call(design, {"dump", "-o", filename});
+ }
+
if (pop_errfile)
log_files.pop_back();
}
@@ -173,6 +188,10 @@ void logv_warning(const char *format, va_list ap)
void logv_error(const char *format, va_list ap)
{
+#ifdef EMSCRIPTEN
+ auto backup_log_files = log_files;
+#endif
+
if (log_errfile != NULL)
log_files.push_back(log_errfile);
@@ -181,10 +200,16 @@ void logv_error(const char *format, va_list ap)
if (f == stdout)
f = stderr;
- log("ERROR: ");
- logv(format, ap);
+ log_last_error = vstringf(format, ap);
+ log("ERROR: %s", log_last_error.c_str());
log_flush();
+
+#ifdef EMSCRIPTEN
+ log_files = backup_log_files;
+ throw 0;
+#else
exit(1);
+#endif
}
void log(const char *format, ...)
@@ -195,11 +220,11 @@ void log(const char *format, ...)
va_end(ap);
}
-void log_header(const char *format, ...)
+void log_header(RTLIL::Design *design, const char *format, ...)
{
va_list ap;
va_start(ap, format);
- logv_header(format, ap);
+ logv_header(design, format, ap);
va_end(ap);
}
@@ -224,8 +249,8 @@ void log_cmd_error(const char *format, ...)
va_start(ap, format);
if (log_cmd_error_throw) {
- log("ERROR: ");
- logv(format, ap);
+ log_last_error = vstringf(format, ap);
+ log("ERROR: %s", log_last_error.c_str());
log_flush();
throw log_cmd_error_exception();
}
@@ -253,7 +278,7 @@ void log_pop()
log_flush();
}
-#ifdef __linux__
+#if defined(__linux__) && defined(YOSYS_ENABLE_PLUGINS)
void log_backtrace(const char *prefix, int levels)
{
if (levels <= 0) return;
@@ -365,6 +390,10 @@ void log_flush()
f->flush();
}
+void log_dump_val_worker(RTLIL::IdString v) {
+ log("%s", log_id(v));
+}
+
void log_dump_val_worker(RTLIL::SigSpec v) {
log("%s", log_signal(v));
}
diff --git a/kernel/log.h b/kernel/log.h
index fd35c7bf7..33e624dcb 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -29,6 +29,11 @@
# include <sys/resource.h>
#endif
+#if defined(_MSC_VER)
+// At least this is not in MSVC++ 2013.
+# define __PRETTY_FUNCTION__ __FUNCTION__
+#endif
+
// from libs/sha1/sha1.h
class SHA1;
@@ -42,6 +47,8 @@ struct log_cmd_error_exception { };
extern std::vector<FILE*> log_files;
extern std::vector<std::ostream*> log_streams;
+extern std::map<std::string, std::set<std::string>> log_hdump;
+extern bool log_hdump_all;
extern FILE *log_errfile;
extern SHA1 *log_hasher;
@@ -50,14 +57,15 @@ extern bool log_error_stderr;
extern bool log_cmd_error_throw;
extern bool log_quiet_warnings;
extern int log_verbose_level;
+extern string log_last_error;
void logv(const char *format, va_list ap);
-void logv_header(const char *format, va_list ap);
+void logv_header(RTLIL::Design *design, const char *format, va_list ap);
void logv_warning(const char *format, va_list ap);
YS_NORETURN void logv_error(const char *format, va_list ap) YS_ATTRIBUTE(noreturn);
void log(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
-void log_header(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
+void log_header(RTLIL::Design *design, const char *format, ...) YS_ATTRIBUTE(format(printf, 2, 3));
void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
@@ -144,7 +152,7 @@ std::string cover_list_worker(std::string prefix, std::string first, T... rest)
// ------------------------------------------------------------
// simple timer for performance measurements
-// toggle the '#if 1' to get a baseline for the perormance penalty added by the measurement
+// toggle the '#if 1' to get a baseline for the performance penalty added by the measurement
struct PerformanceTimer
{
#if 1
@@ -155,11 +163,13 @@ struct PerformanceTimer
}
static int64_t query() {
-#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
+# if _WIN32
+ return 0;
+# elif defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
struct timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
return int64_t(ts.tv_sec)*1000000000 + ts.tv_nsec;
-#elif defined(RUSAGE_SELF)
+# elif defined(RUSAGE_SELF)
struct rusage rusage;
int64_t t;
if (getrusage(RUSAGE_SELF, &rusage) == -1) {
@@ -169,11 +179,9 @@ struct PerformanceTimer
t = 1000000000ULL * (int64_t) rusage.ru_utime.tv_sec + (int64_t) rusage.ru_utime.tv_usec * 1000ULL;
t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL;
return t;
-#elif _WIN32
- return 0;
-#else
- #error Dont know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?).
-#endif
+# else
+# error Dont know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?).
+# endif
}
void reset() {
@@ -221,8 +229,35 @@ static inline void log_dump_val_worker(const char *v) { log("%s", v); }
static inline void log_dump_val_worker(std::string v) { log("%s", v.c_str()); }
static inline void log_dump_val_worker(PerformanceTimer p) { log("%f seconds", p.sec()); }
static inline void log_dump_args_worker(const char *p YS_ATTRIBUTE(unused)) { log_assert(*p == 0); }
+void log_dump_val_worker(RTLIL::IdString v);
void log_dump_val_worker(RTLIL::SigSpec v);
+template<typename K, typename T, typename OPS>
+static inline void log_dump_val_worker(dict<K, T, OPS> &v) {
+ log("{");
+ bool first = true;
+ for (auto &it : v) {
+ log(first ? " " : ", ");
+ log_dump_val_worker(it.first);
+ log(": ");
+ log_dump_val_worker(it.second);
+ first = false;
+ }
+ log(" }");
+}
+
+template<typename K, typename OPS>
+static inline void log_dump_val_worker(pool<K, OPS> &v) {
+ log("{");
+ bool first = true;
+ for (auto &it : v) {
+ log(first ? " " : ", ");
+ log_dump_val_worker(it);
+ first = false;
+ }
+ log(" }");
+}
+
template<typename T>
static inline void log_dump_val_worker(T *ptr) { log("%p", ptr); }
diff --git a/kernel/macc.h b/kernel/macc.h
index cac5b00d7..286ce567f 100644
--- a/kernel/macc.h
+++ b/kernel/macc.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -158,8 +158,8 @@ struct Macc
int max_size = 0, num_bits = 0;
for (auto &port : ports) {
- max_size = std::max(max_size, GetSize(port.in_a));
- max_size = std::max(max_size, GetSize(port.in_b));
+ max_size = max(max_size, GetSize(port.in_a));
+ max_size = max(max_size, GetSize(port.in_b));
}
while (max_size)
diff --git a/kernel/modtools.h b/kernel/modtools.h
index 69c13bd3b..ffcb48d44 100644
--- a/kernel/modtools.h
+++ b/kernel/modtools.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -180,8 +180,8 @@ struct ModIndex : public RTLIL::Monitor
{
RTLIL::SigBit lhs = sigmap(sigsig.first[i]);
RTLIL::SigBit rhs = sigmap(sigsig.second[i]);
- bool has_lhs = database.count(lhs);
- bool has_rhs = database.count(rhs);
+ bool has_lhs = database.count(lhs) != 0;
+ bool has_rhs = database.count(rhs) != 0;
if (!has_lhs && !has_rhs) {
sigmap.add(lhs, rhs);
@@ -226,7 +226,7 @@ struct ModIndex : public RTLIL::Monitor
auto_reload_module = true;
}
- ModIndex(RTLIL::Module *_m) : module(_m)
+ ModIndex(RTLIL::Module *_m) : sigmap(_m), module(_m)
{
auto_reload_counter = 0;
auto_reload_module = true;
@@ -274,6 +274,27 @@ struct ModIndex : public RTLIL::Monitor
return empty_result_set;
return info->ports;
}
+
+ void dump_db()
+ {
+ log("--- ModIndex Dump ---\n");
+
+ if (auto_reload_module) {
+ log("AUTO-RELOAD\n");
+ reload_module();
+ }
+
+ for (auto &it : database) {
+ log("BIT %s:\n", log_signal(it.first));
+ if (it.second.is_input)
+ log(" PRIMARY INPUT\n");
+ if (it.second.is_output)
+ log(" PRIMARY OUTPUT\n");
+ for (auto &port : it.second.ports)
+ log(" PORT: %s.%s[%d] (%s)\n", log_id(port.cell),
+ log_id(port.port), port.offset, log_id(port.cell->type));
+ }
+ }
};
struct ModWalker
diff --git a/kernel/register.cc b/kernel/register.cc
index 56dc695aa..115880ed6 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -18,6 +18,8 @@
*/
#include "kernel/yosys.h"
+#include "kernel/satgen.h"
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -78,6 +80,7 @@ Pass::pre_post_exec_state_t Pass::pre_execute()
state.begin_ns = PerformanceTimer::query();
state.parent_pass = current_pass;
current_pass = this;
+ clear_flags();
return state;
}
@@ -97,6 +100,10 @@ void Pass::help()
log("\n");
}
+void Pass::clear_flags()
+{
+}
+
void Pass::cmd_log_args(const std::vector<std::string> &args)
{
if (args.size() <= 1)
@@ -148,7 +155,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
std::vector<std::string> args;
std::string cmd_buf = command;
- std::string tok = next_token(cmd_buf, " \t\r\n");
+ std::string tok = next_token(cmd_buf, " \t\r\n", true);
if (tok.empty())
return;
@@ -158,7 +165,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' ||
cmd_buf.back() == '\r' || cmd_buf.back() == '\n'))
cmd_buf.resize(cmd_buf.size()-1);
- log_header("Shell command: %s\n", cmd_buf.c_str());
+ log_header(design, "Shell command: %s\n", cmd_buf.c_str());
int retCode = run_command(cmd_buf);
if (retCode != 0)
log_cmd_error("Shell command returned error code %d.\n", retCode);
@@ -199,7 +206,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
call(design, args);
args.clear();
}
- tok = next_token(cmd_buf, " \t\r\n");
+ tok = next_token(cmd_buf, " \t\r\n", true);
}
call(design, args);
@@ -207,7 +214,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
{
- if (args.size() == 0 || args[0][0] == '#')
+ if (args.size() == 0 || args[0][0] == '#' || args[0][0] == ':')
return;
if (echo_mode) {
@@ -280,6 +287,60 @@ void Pass::call_on_module(RTLIL::Design *design, RTLIL::Module *module, std::vec
design->selected_active_module = backup_selected_active_module;
}
+bool ScriptPass::check_label(std::string label, std::string info)
+{
+ if (active_design == nullptr) {
+ log("\n");
+ if (info.empty())
+ log(" %s:\n", label.c_str());
+ else
+ log(" %s: %s\n", label.c_str(), info.c_str());
+ return true;
+ } else {
+ if (!active_run_from.empty() && active_run_from == active_run_to) {
+ block_active = (label == active_run_from);
+ } else {
+ if (label == active_run_from)
+ block_active = true;
+ if (label == active_run_to)
+ block_active = false;
+ }
+ return block_active;
+ }
+}
+
+void ScriptPass::run(std::string command, std::string info)
+{
+ if (active_design == nullptr) {
+ if (info.empty())
+ log(" %s\n", command.c_str());
+ else
+ log(" %s %s\n", command.c_str(), info.c_str());
+ } else
+ Pass::call(active_design, command);
+}
+
+void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to)
+{
+ help_mode = false;
+ active_design = design;
+ block_active = run_from.empty();
+ active_run_from = run_from;
+ active_run_to = run_to;
+ script();
+}
+
+void ScriptPass::help_script()
+{
+ clear_flags();
+ help_mode = true;
+ active_design = nullptr;
+ block_active = true;
+ active_run_from.clear();
+ active_run_to.clear();
+ script();
+}
+
Frontend::Frontend(std::string name, std::string short_help) :
Pass(name.rfind("=", 0) == 0 ? name.substr(1) : "read_" + name, short_help),
frontend_name(name.rfind("=", 0) == 0 ? name.substr(1) : name)
@@ -357,8 +418,7 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s
}
f = new std::istringstream(last_here_document);
} else {
- if (filename.substr(0, 2) == "+/")
- filename = proc_share_dirname() + filename.substr(1);
+ rewrite_filename(filename);
std::ifstream *ff = new std::ifstream;
ff->open(filename.c_str());
if (ff->fail())
@@ -533,23 +593,36 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f
design->check();
}
+static struct CellHelpMessages {
+ dict<string, string> cell_help, cell_code;
+ CellHelpMessages() {
+#include "techlibs/common/simlib_help.inc"
+#include "techlibs/common/simcells_help.inc"
+ cell_help.sort();
+ cell_code.sort();
+ }
+} cell_help_messages;
+
struct HelpPass : public Pass {
HelpPass() : Pass("help", "display help messages") { }
virtual void help()
{
log("\n");
- log(" help ............. list all commands\n");
- log(" help <command> ... print help message for given command\n");
- log(" help -all ........ print complete command reference\n");
+ log(" help ................ list all commands\n");
+ log(" help <command> ...... print help message for given command\n");
+ log(" help -all ........... print complete command reference\n");
+ log("\n");
+ log(" help -cells .......... list all cell types\n");
+ log(" help <celltype> ..... print help message for given cell type\n");
+ log(" help <celltype>+ .... print verilog code for given cell type\n");
log("\n");
}
void escape_tex(std::string &tex)
{
- size_t pos = 0;
- while ((pos = tex.find('_', pos)) != std::string::npos) {
+ for (size_t pos = 0; (pos = tex.find('_', pos)) != std::string::npos; pos += 2)
tex.replace(pos, 1, "\\_");
- pos += 2;
- }
+ for (size_t pos = 0; (pos = tex.find('$', pos)) != std::string::npos; pos += 2)
+ tex.replace(pos, 1, "\\$");
}
void write_tex(FILE *f, std::string cmd, std::string title, std::string text)
{
@@ -609,6 +682,7 @@ struct HelpPass : public Pass {
log(" %-20s %s\n", it.first.c_str(), it.second->short_help.c_str());
log("\n");
log("Type 'help <command>' for more information on a command.\n");
+ log("Type 'help -cells' for a list of all cell types.\n");
log("\n");
return;
}
@@ -624,6 +698,18 @@ struct HelpPass : public Pass {
it.second->help();
}
}
+ else if (args[1] == "-cells") {
+ log("\n");
+ for (auto &it : cell_help_messages.cell_help) {
+ string line = split_tokens(it.second, "\n").at(0);
+ string cell_name = next_token(line);
+ log(" %-15s %s\n", cell_name.c_str(), line.c_str());
+ }
+ log("\n");
+ log("Type 'help <cell_type>' for more information on a cell type.\n");
+ log("\n");
+ return;
+ }
// this option is undocumented as it is for internal use only
else if (args[1] == "-write-tex-command-reference-manual") {
FILE *f = fopen("command-reference-manual.tex", "wt");
@@ -649,17 +735,27 @@ struct HelpPass : public Pass {
}
fclose(f);
}
- else if (pass_register.count(args[1]) == 0)
- log("No such command: %s\n", args[1].c_str());
- else
+ else if (pass_register.count(args[1])) {
pass_register.at(args[1])->help();
+ }
+ else if (cell_help_messages.cell_help.count(args[1])) {
+ log("%s", cell_help_messages.cell_help.at(args[1]).c_str());
+ log("Run 'help %s+' to display the Verilog model for this cell type.\n", args[1].c_str());
+ log("\n");
+ }
+ else if (cell_help_messages.cell_code.count(args[1])) {
+ log("\n");
+ log("%s", cell_help_messages.cell_code.at(args[1]).c_str());
+ }
+ else
+ log("No such command or cell type: %s\n", args[1].c_str());
return;
}
help();
}
} HelpPass;
-
+
struct EchoPass : public Pass {
EchoPass() : Pass("echo", "turning echoing back of commands on and off") { }
virtual void help()
@@ -692,6 +788,18 @@ struct EchoPass : public Pass {
log("echo %s\n", echo_mode ? "on" : "off");
}
} EchoPass;
-
+
+SatSolver *yosys_satsolver_list;
+SatSolver *yosys_satsolver;
+
+struct MinisatSatSolver : public SatSolver {
+ MinisatSatSolver() : SatSolver("minisat") {
+ yosys_satsolver = this;
+ }
+ virtual ezSAT *create() YS_OVERRIDE {
+ return new ezMiniSAT();
+ }
+} MinisatSatSolver;
+
YOSYS_NAMESPACE_END
diff --git a/kernel/register.h b/kernel/register.h
index 71ab6ea6e..8024c56a0 100644
--- a/kernel/register.h
+++ b/kernel/register.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -31,6 +31,7 @@ struct Pass
virtual ~Pass();
virtual void help();
+ virtual void clear_flags();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) = 0;
int call_counter;
@@ -63,6 +64,22 @@ struct Pass
static void done_register();
};
+struct ScriptPass : Pass
+{
+ bool block_active, help_mode;
+ RTLIL::Design *active_design;
+ std::string active_run_from, active_run_to;
+
+ ScriptPass(std::string name, std::string short_help = "** document me **") : Pass(name, short_help) { }
+
+ virtual void script() = 0;
+
+ bool check_label(std::string label, std::string info = std::string());
+ void run(std::string command, std::string info = std::string());
+ void run_script(RTLIL::Design *design, std::string run_from = std::string(), std::string run_to = std::string());
+ void help_script();
+};
+
struct Frontend : Pass
{
// for reading of here documents
@@ -71,7 +88,7 @@ struct Frontend : Pass
std::string frontend_name;
Frontend(std::string name, std::string short_help = "** document me **");
- virtual void run_register();
+ virtual void run_register() YS_OVERRIDE;
virtual ~Frontend();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL;
virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
@@ -87,7 +104,7 @@ struct Backend : Pass
{
std::string backend_name;
Backend(std::string name, std::string short_help = "** document me **");
- virtual void run_register();
+ virtual void run_register() YS_OVERRIDE;
virtual ~Backend();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE YS_FINAL;
virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 776625b9c..9da6d2816 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -147,7 +147,7 @@ RTLIL::Const RTLIL::Const::from_string(std::string str)
std::string RTLIL::Const::decode_string() const
{
std::string string;
- std::vector <char> string_chars;
+ std::vector<char> string_chars;
for (int i = 0; i < int (bits.size()); i += 8) {
char ch = 0;
for (int j = 0; j < 8 && i + j < int (bits.size()); j++)
@@ -161,6 +161,46 @@ std::string RTLIL::Const::decode_string() const
return string;
}
+void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id)
+{
+ attributes[id] = RTLIL::Const(1);
+}
+
+bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const
+{
+ if (attributes.count(id) == 0)
+ return false;
+ return attributes.at(id).as_bool();
+}
+
+void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool<string> &data)
+{
+ string attrval;
+ for (auto &s : data) {
+ if (!attrval.empty())
+ attrval += "|";
+ attrval += s;
+ }
+ attributes[id] = RTLIL::Const(attrval);
+}
+
+void RTLIL::AttrObject::add_strpool_attribute(RTLIL::IdString id, const pool<string> &data)
+{
+ pool<string> union_data = get_strpool_attribute(id);
+ union_data.insert(data.begin(), data.end());
+ if (!union_data.empty())
+ set_strpool_attribute(id, union_data);
+}
+
+pool<string> RTLIL::AttrObject::get_strpool_attribute(RTLIL::IdString id) const
+{
+ pool<string> data;
+ if (attributes.count(id) != 0)
+ for (auto s : split_tokens(attributes.at(id).decode_string(), "|"))
+ data.insert(s);
+ return data;
+}
+
bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const
{
if (full_selection)
@@ -264,6 +304,8 @@ RTLIL::Design::~Design()
{
for (auto it = modules_.begin(); it != modules_.end(); ++it)
delete it->second;
+ for (auto n : verilog_packages)
+ delete n;
}
RTLIL::ObjRange<RTLIL::Module*> RTLIL::Design::modules()
@@ -276,6 +318,21 @@ RTLIL::Module *RTLIL::Design::module(RTLIL::IdString name)
return modules_.count(name) ? modules_.at(name) : NULL;
}
+RTLIL::Module *RTLIL::Design::top_module()
+{
+ RTLIL::Module *module = nullptr;
+ int module_count = 0;
+
+ for (auto mod : selected_modules()) {
+ if (mod->get_bool_attribute("\\top"))
+ return mod;
+ module_count++;
+ module = mod;
+ }
+
+ return module_count == 1 ? module : nullptr;
+}
+
void RTLIL::Design::add(RTLIL::Module *module)
{
log_assert(modules_.count(module->name) == 0);
@@ -389,6 +446,13 @@ void RTLIL::Design::remove(RTLIL::Module *module)
delete module;
}
+void RTLIL::Design::rename(RTLIL::Module *module, RTLIL::IdString new_name)
+{
+ modules_.erase(module->name);
+ module->name = new_name;
+ add(module);
+}
+
void RTLIL::Design::sort()
{
scratchpad.sort();
@@ -783,6 +847,15 @@ namespace {
return;
}
+ if (cell->type == "$sop") {
+ param("\\DEPTH");
+ param("\\TABLE");
+ port("\\A", param("\\WIDTH"));
+ port("\\Y", 1);
+ check_expected();
+ return;
+ }
+
if (cell->type == "$sr") {
param_bool("\\SET_POLARITY");
param_bool("\\CLR_POLARITY");
@@ -885,6 +958,7 @@ namespace {
param_bool("\\CLK_POLARITY");
param_bool("\\TRANSPARENT");
port("\\CLK", 1);
+ port("\\EN", 1);
port("\\ADDR", param("\\ABITS"));
port("\\DATA", param("\\WIDTH"));
check_expected();
@@ -904,16 +978,27 @@ namespace {
return;
}
+ if (cell->type == "$meminit") {
+ param("\\MEMID");
+ param("\\PRIORITY");
+ port("\\ADDR", param("\\ABITS"));
+ port("\\DATA", param("\\WIDTH") * param("\\WORDS"));
+ check_expected();
+ return;
+ }
+
if (cell->type == "$mem") {
param("\\MEMID");
param("\\SIZE");
param("\\OFFSET");
- param_bits("\\RD_CLK_ENABLE", param("\\RD_PORTS"));
- param_bits("\\RD_CLK_POLARITY", param("\\RD_PORTS"));
- param_bits("\\RD_TRANSPARENT", param("\\RD_PORTS"));
- param_bits("\\WR_CLK_ENABLE", param("\\WR_PORTS"));
- param_bits("\\WR_CLK_POLARITY", param("\\WR_PORTS"));
+ param("\\INIT");
+ param_bits("\\RD_CLK_ENABLE", max(1, param("\\RD_PORTS")));
+ param_bits("\\RD_CLK_POLARITY", max(1, param("\\RD_PORTS")));
+ param_bits("\\RD_TRANSPARENT", max(1, param("\\RD_PORTS")));
+ param_bits("\\WR_CLK_ENABLE", max(1, param("\\WR_PORTS")));
+ param_bits("\\WR_CLK_POLARITY", max(1, param("\\WR_PORTS")));
port("\\RD_CLK", param("\\RD_PORTS"));
+ port("\\RD_EN", param("\\RD_PORTS"));
port("\\RD_ADDR", param("\\RD_PORTS") * param("\\ABITS"));
port("\\RD_DATA", param("\\RD_PORTS") * param("\\WIDTH"));
port("\\WR_CLK", param("\\WR_PORTS"));
@@ -924,6 +1009,14 @@ namespace {
return;
}
+ if (cell->type == "$tribuf") {
+ port("\\A", param("\\WIDTH"));
+ port("\\Y", param("\\WIDTH"));
+ port("\\EN", 1);
+ check_expected();
+ return;
+ }
+
if (cell->type == "$assert") {
port("\\A", 1);
port("\\EN", 1);
@@ -931,6 +1024,13 @@ namespace {
return;
}
+ if (cell->type == "$assume") {
+ port("\\A", 1);
+ port("\\EN", 1);
+ check_expected();
+ return;
+ }
+
if (cell->type == "$equiv") {
port("\\A", 1);
port("\\B", 1);
@@ -953,6 +1053,12 @@ namespace {
if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; }
if (cell->type == "$_OAI4_") { check_gate("ABCDY"); return; }
+ if (cell->type == "$_TBUF_") { check_gate("AYE"); return; }
+
+ if (cell->type == "$_MUX4_") { check_gate("ABCDSTY"); return; }
+ if (cell->type == "$_MUX8_") { check_gate("ABCDEFGHSTUY"); return; }
+ if (cell->type == "$_MUX16_") { check_gate("ABCDEFGHIJKLMNOPSTUVY"); return; }
+
if (cell->type == "$_SR_NN_") { check_gate("SRQ"); return; }
if (cell->type == "$_SR_NP_") { check_gate("SRQ"); return; }
if (cell->type == "$_SR_PN_") { check_gate("SRQ"); return; }
@@ -1097,6 +1203,8 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod) const
log_assert(new_mod->refcount_wires_ == 0);
log_assert(new_mod->refcount_cells_ == 0);
+ new_mod->avail_parameters = avail_parameters;
+
for (auto &conn : connections_)
new_mod->connect(conn);
@@ -1351,6 +1459,19 @@ void RTLIL::Module::connect(const RTLIL::SigSig &conn)
for (auto mon : design->monitors)
mon->notify_connect(this, conn);
+ // ignore all attempts to assign constants to other constants
+ if (conn.first.has_const()) {
+ RTLIL::SigSig new_conn;
+ for (int i = 0; i < GetSize(conn.first); i++)
+ if (conn.first[i].wire) {
+ new_conn.first.append(conn.first[i]);
+ new_conn.second.append(conn.second[i]);
+ }
+ if (GetSize(new_conn.first))
+ connect(new_conn);
+ return;
+ }
+
if (yosys_xtrace) {
log("#X# Connect (SigSig) in %s: %s = %s (%d bits)\n", log_id(this), log_signal(conn.first), log_signal(conn.second), GetSize(conn.first));
log_backtrace("-X- ", yosys_xtrace-1);
@@ -1491,10 +1612,10 @@ DEF_METHOD(LogicNot, 1, "$logic_not")
add ## _func(name, sig_a, sig_b, sig_y, is_signed); \
return sig_y; \
}
-DEF_METHOD(And, std::max(sig_a.size(), sig_b.size()), "$and")
-DEF_METHOD(Or, std::max(sig_a.size(), sig_b.size()), "$or")
-DEF_METHOD(Xor, std::max(sig_a.size(), sig_b.size()), "$xor")
-DEF_METHOD(Xnor, std::max(sig_a.size(), sig_b.size()), "$xnor")
+DEF_METHOD(And, max(sig_a.size(), sig_b.size()), "$and")
+DEF_METHOD(Or, max(sig_a.size(), sig_b.size()), "$or")
+DEF_METHOD(Xor, max(sig_a.size(), sig_b.size()), "$xor")
+DEF_METHOD(Xnor, max(sig_a.size(), sig_b.size()), "$xnor")
DEF_METHOD(Shl, sig_a.size(), "$shl")
DEF_METHOD(Shr, sig_a.size(), "$shr")
DEF_METHOD(Sshl, sig_a.size(), "$sshl")
@@ -1509,11 +1630,11 @@ DEF_METHOD(Eqx, 1, "$eqx")
DEF_METHOD(Nex, 1, "$nex")
DEF_METHOD(Ge, 1, "$ge")
DEF_METHOD(Gt, 1, "$gt")
-DEF_METHOD(Add, std::max(sig_a.size(), sig_b.size()), "$add")
-DEF_METHOD(Sub, std::max(sig_a.size(), sig_b.size()), "$sub")
-DEF_METHOD(Mul, std::max(sig_a.size(), sig_b.size()), "$mul")
-DEF_METHOD(Div, std::max(sig_a.size(), sig_b.size()), "$div")
-DEF_METHOD(Mod, std::max(sig_a.size(), sig_b.size()), "$mod")
+DEF_METHOD(Add, max(sig_a.size(), sig_b.size()), "$add")
+DEF_METHOD(Sub, max(sig_a.size(), sig_b.size()), "$sub")
+DEF_METHOD(Mul, max(sig_a.size(), sig_b.size()), "$mul")
+DEF_METHOD(Div, max(sig_a.size(), sig_b.size()), "$div")
+DEF_METHOD(Mod, max(sig_a.size(), sig_b.size()), "$mod")
DEF_METHOD(LogicAnd, 1, "$logic_and")
DEF_METHOD(LogicOr, 1, "$logic_or")
#undef DEF_METHOD
@@ -1592,6 +1713,7 @@ DEF_METHOD(Pmux, "$pmux", 1)
add ## _func(name, sig1, sig2, sig3, sig4, sig5); \
return sig5; \
}
+DEF_METHOD_2(BufGate, "$_BUF_", A, Y)
DEF_METHOD_2(NotGate, "$_NOT_", A, Y)
DEF_METHOD_3(AndGate, "$_AND_", A, B, Y)
DEF_METHOD_3(NandGate, "$_NAND_", A, B, Y)
@@ -1645,13 +1767,23 @@ RTLIL::Cell* RTLIL::Module::addConcat(RTLIL::IdString name, RTLIL::SigSpec sig_a
return cell;
}
-RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, RTLIL::SigSpec sig_i, RTLIL::SigSpec sig_o, RTLIL::Const lut)
+RTLIL::Cell* RTLIL::Module::addLut(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const lut)
{
RTLIL::Cell *cell = addCell(name, "$lut");
cell->parameters["\\LUT"] = lut;
- cell->parameters["\\WIDTH"] = sig_i.size();
- cell->setPort("\\A", sig_i);
- cell->setPort("\\Y", sig_o);
+ cell->parameters["\\WIDTH"] = sig_a.size();
+ cell->setPort("\\A", sig_a);
+ cell->setPort("\\Y", sig_y);
+ return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addTribuf(RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_y)
+{
+ RTLIL::Cell *cell = addCell(name, "$tribuf");
+ cell->parameters["\\WIDTH"] = sig_a.size();
+ cell->setPort("\\A", sig_a);
+ cell->setPort("\\EN", sig_en);
+ cell->setPort("\\Y", sig_y);
return cell;
}
@@ -2012,7 +2144,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
return;
}
- if (type == "$lut") {
+ if (type == "$lut" || type == "$sop") {
parameters["\\WIDTH"] = GetSize(connections_["\\A"]);
return;
}
@@ -2453,8 +2585,18 @@ void RTLIL::SigSpec::sort()
void RTLIL::SigSpec::sort_and_unify()
{
+ unpack();
cover("kernel.rtlil.sigspec.sort_and_unify");
- *this = this->to_sigbit_set();
+
+ // A copy of the bits vector is used to prevent duplicating the logic from
+ // SigSpec::SigSpec(std::vector<SigBit>). This incurrs an extra copy but
+ // that isn't showing up as significant in profiles.
+ std::vector<SigBit> unique_bits = bits_;
+ std::sort(unique_bits.begin(), unique_bits.end());
+ auto last = std::unique(unique_bits.begin(), unique_bits.end());
+ unique_bits.erase(last, unique_bits.end());
+
+ *this = unique_bits;
}
void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
@@ -2464,18 +2606,26 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec
void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const
{
+ log_assert(other != NULL);
+ log_assert(width_ == other->width_);
log_assert(pattern.width_ == with.width_);
pattern.unpack();
with.unpack();
+ unpack();
+ other->unpack();
- dict<RTLIL::SigBit, RTLIL::SigBit> rules;
-
- for (int i = 0; i < GetSize(pattern.bits_); i++)
- if (pattern.bits_[i].wire != NULL)
- rules[pattern.bits_[i]] = with.bits_[i];
+ for (int i = 0; i < GetSize(pattern.bits_); i++) {
+ if (pattern.bits_[i].wire != NULL) {
+ for (int j = 0; j < GetSize(bits_); j++) {
+ if (bits_[j] == pattern.bits_[i]) {
+ other->bits_[j] = with.bits_[i];
+ }
+ }
+ }
+ }
- replace(rules, other);
+ other->check();
}
void RTLIL::SigSpec::replace(const dict<RTLIL::SigBit, RTLIL::SigBit> &rules)
@@ -2539,8 +2689,35 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other
void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other)
{
- pool<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_pool();
- remove2(pattern_bits, other);
+ if (other)
+ cover("kernel.rtlil.sigspec.remove_other");
+ else
+ cover("kernel.rtlil.sigspec.remove");
+
+ unpack();
+ if (other != NULL) {
+ log_assert(width_ == other->width_);
+ other->unpack();
+ }
+
+ for (int i = GetSize(bits_) - 1; i >= 0; i--) {
+ if (bits_[i].wire == NULL) continue;
+
+ for (auto &pattern_chunk : pattern.chunks()) {
+ if (bits_[i].wire == pattern_chunk.wire &&
+ bits_[i].offset >= pattern_chunk.offset &&
+ bits_[i].offset < pattern_chunk.offset + pattern_chunk.width) {
+ bits_.erase(bits_.begin() + i);
+ width_--;
+ if (other != NULL) {
+ other->bits_.erase(other->bits_.begin() + i);
+ other->width_--;
+ }
+ }
+ }
+ }
+
+ check();
}
void RTLIL::SigSpec::remove(const pool<RTLIL::SigBit> &pattern)
@@ -2568,31 +2745,43 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec
other->unpack();
}
- std::vector<RTLIL::SigBit> new_bits, new_other_bits;
-
- new_bits.resize(GetSize(bits_));
- if (other != NULL)
- new_other_bits.resize(GetSize(bits_));
-
- int k = 0;
- for (int i = 0; i < GetSize(bits_); i++) {
- if (bits_[i].wire != NULL && pattern.count(bits_[i]))
- continue;
- if (other != NULL)
- new_other_bits[k] = other->bits_[i];
- new_bits[k++] = bits_[i];
+ for (int i = GetSize(bits_) - 1; i >= 0; i--) {
+ if (bits_[i].wire != NULL && pattern.count(bits_[i])) {
+ bits_.erase(bits_.begin() + i);
+ width_--;
+ if (other != NULL) {
+ other->bits_.erase(other->bits_.begin() + i);
+ other->width_--;
+ }
+ }
}
- new_bits.resize(k);
- if (other != NULL)
- new_other_bits.resize(k);
+ check();
+}
- bits_.swap(new_bits);
- width_ = GetSize(bits_);
+void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other)
+{
+ if (other)
+ cover("kernel.rtlil.sigspec.remove_other");
+ else
+ cover("kernel.rtlil.sigspec.remove");
+
+ unpack();
if (other != NULL) {
- other->bits_.swap(new_other_bits);
- other->width_ = GetSize(other->bits_);
+ log_assert(width_ == other->width_);
+ other->unpack();
+ }
+
+ for (int i = GetSize(bits_) - 1; i >= 0; i--) {
+ if (bits_[i].wire != NULL && pattern.count(bits_[i])) {
+ bits_.erase(bits_.begin() + i);
+ width_--;
+ if (other != NULL) {
+ other->bits_.erase(other->bits_.begin() + i);
+ other->width_--;
+ }
+ }
}
check();
@@ -2600,8 +2789,37 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec
RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const
{
- pool<RTLIL::SigBit> pattern_bits = pattern.to_sigbit_pool();
- return extract(pattern_bits, other);
+ if (other)
+ cover("kernel.rtlil.sigspec.extract_other");
+ else
+ cover("kernel.rtlil.sigspec.extract");
+
+ log_assert(other == NULL || width_ == other->width_);
+
+ RTLIL::SigSpec ret;
+ std::vector<RTLIL::SigBit> bits_match = to_sigbit_vector();
+
+ for (auto& pattern_chunk : pattern.chunks()) {
+ if (other) {
+ std::vector<RTLIL::SigBit> bits_other = other->to_sigbit_vector();
+ for (int i = 0; i < width_; i++)
+ if (bits_match[i].wire &&
+ bits_match[i].wire == pattern_chunk.wire &&
+ bits_match[i].offset >= pattern_chunk.offset &&
+ bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width)
+ ret.append_bit(bits_other[i]);
+ } else {
+ for (int i = 0; i < width_; i++)
+ if (bits_match[i].wire &&
+ bits_match[i].wire == pattern_chunk.wire &&
+ bits_match[i].offset >= pattern_chunk.offset &&
+ bits_match[i].offset < pattern_chunk.offset + pattern_chunk.width)
+ ret.append_bit(bits_match[i]);
+ }
+ }
+
+ ret.check();
+ return ret;
}
RTLIL::SigSpec RTLIL::SigSpec::extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other) const
@@ -2785,7 +3003,7 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed)
if (width_ > width)
remove(width, width_ - width);
-
+
if (width_ < width) {
RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0;
if (!is_signed)
@@ -2939,6 +3157,21 @@ bool RTLIL::SigSpec::is_fully_const() const
return true;
}
+bool RTLIL::SigSpec::is_fully_zero() const
+{
+ cover("kernel.rtlil.sigspec.is_fully_zero");
+
+ pack();
+ for (auto it = chunks_.begin(); it != chunks_.end(); it++) {
+ if (it->width > 0 && it->wire != NULL)
+ return false;
+ for (size_t i = 0; i < it->data.size(); i++)
+ if (it->data[i] != RTLIL::State::S0)
+ return false;
+ }
+ return true;
+}
+
bool RTLIL::SigSpec::is_fully_def() const
{
cover("kernel.rtlil.sigspec.is_fully_def");
@@ -3062,6 +3295,17 @@ RTLIL::SigChunk RTLIL::SigSpec::as_chunk() const
return chunks_[0];
}
+RTLIL::SigBit RTLIL::SigSpec::as_bit() const
+{
+ cover("kernel.rtlil.sigspec.as_bit");
+
+ log_assert(width_ == 1);
+ if (packed())
+ return RTLIL::SigBit(*chunks_.begin());
+ else
+ return bits_[0];
+}
+
bool RTLIL::SigSpec::match(std::string pattern) const
{
cover("kernel.rtlil.sigspec.match");
@@ -3149,18 +3393,6 @@ dict<RTLIL::SigBit, RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_dict(const RTLIL::S
return new_map;
}
-RTLIL::SigBit RTLIL::SigSpec::to_single_sigbit() const
-{
- cover("kernel.rtlil.sigspec.to_single_sigbit");
-
- pack();
- log_assert(width_ == 1);
- for (auto &c : chunks_)
- if (c.width)
- return RTLIL::SigBit(c);
- log_abort();
-}
-
static void sigspec_parse_split(std::vector<std::string> &tokens, const std::string &text, char sep)
{
size_t start = 0, end = 0;
@@ -3180,6 +3412,10 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri
{
cover("kernel.rtlil.sigspec.parse");
+ AST::current_filename = "input";
+ AST::use_internal_line_num();
+ AST::set_line_num(0);
+
std::vector<std::string> tokens;
sigspec_parse_split(tokens, str, ',');
@@ -3339,7 +3575,7 @@ RTLIL::SwitchRule *RTLIL::SwitchRule::clone() const
for (auto &it : cases)
new_switchrule->cases.push_back(it->clone());
return new_switchrule;
-
+
}
RTLIL::SyncRule *RTLIL::SyncRule::clone() const
@@ -3371,7 +3607,7 @@ RTLIL::Process *RTLIL::Process::clone() const
for (auto &it : syncs)
new_proc->syncs.push_back(it->clone());
-
+
return new_proc;
}
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index dd40e2fba..274f97023 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -53,6 +53,7 @@ namespace RTLIL
};
struct Const;
+ struct AttrObject;
struct Selection;
struct Monitor;
struct Design;
@@ -191,14 +192,14 @@ namespace RTLIL
return std::string(global_id_storage_.at(index_));
}
- bool operator<(IdString rhs) const {
+ bool operator<(const IdString &rhs) const {
return index_ < rhs.index_;
}
- bool operator==(IdString rhs) const { return index_ == rhs.index_; }
- bool operator!=(IdString rhs) const { return index_ != rhs.index_; }
+ bool operator==(const IdString &rhs) const { return index_ == rhs.index_; }
+ bool operator!=(const IdString &rhs) const { return index_ != rhs.index_; }
- // The methods below are just convinience functions for better compatibility with std::string.
+ // The methods below are just convenience functions for better compatibility with std::string.
bool operator==(const std::string &rhs) const { return str() == rhs; }
bool operator!=(const std::string &rhs) const { return str() != rhs; }
@@ -208,7 +209,7 @@ namespace RTLIL
char operator[](size_t i) const {
const char *p = c_str();
- for (; i != 0; i--, p++)
+ for (; i != 0; i--, p++)
log_assert(*p != 0);
return *p;
}
@@ -459,7 +460,7 @@ struct RTLIL::Const
Const(std::string str);
Const(int val, int width = 32);
Const(RTLIL::State bit, int width = 1);
- Const(const std::vector<RTLIL::State> &bits) : bits(bits) { flags = CONST_FLAG_NONE; };
+ Const(const std::vector<RTLIL::State> &bits) : bits(bits) { flags = CONST_FLAG_NONE; }
Const(const std::vector<bool> &bits);
bool operator <(const RTLIL::Const &other) const;
@@ -474,6 +475,16 @@ struct RTLIL::Const
std::string decode_string() const;
inline int size() const { return bits.size(); }
+ inline RTLIL::State &operator[](int index) { return bits.at(index); }
+ inline const RTLIL::State &operator[](int index) const { return bits.at(index); }
+
+ inline RTLIL::Const extract(int offset, int len = 1, RTLIL::State padding = RTLIL::State::S0) const {
+ RTLIL::Const ret;
+ ret.bits.reserve(len);
+ for (int i = offset; i < offset + len; i++)
+ ret.bits.push_back(i < GetSize(bits) ? bits[i] : padding);
+ return ret;
+ }
inline unsigned int hash() const {
unsigned int h = mkhash_init;
@@ -483,6 +494,17 @@ struct RTLIL::Const
}
};
+struct RTLIL::AttrObject
+{
+ dict<RTLIL::IdString, RTLIL::Const> attributes;
+
+ void set_bool_attribute(RTLIL::IdString id);
+ bool get_bool_attribute(RTLIL::IdString id) const;
+ void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
+ void add_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
+ pool<string> get_strpool_attribute(RTLIL::IdString id) const;
+};
+
struct RTLIL::SigChunk
{
RTLIL::Wire *wire;
@@ -647,6 +669,7 @@ public:
void remove(const pool<RTLIL::SigBit> &pattern);
void remove(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other) const;
void remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other);
+ void remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigSpec *other);
void remove(int offset, int length = 1);
void remove_const();
@@ -668,8 +691,10 @@ public:
bool is_wire() const;
bool is_chunk() const;
+ inline bool is_bit() const { return width_ == 1; }
bool is_fully_const() const;
+ bool is_fully_zero() const;
bool is_fully_def() const;
bool is_fully_undef() const;
bool has_const() const;
@@ -681,6 +706,7 @@ public:
RTLIL::Const as_const() const;
RTLIL::Wire *as_wire() const;
RTLIL::SigChunk as_chunk() const;
+ RTLIL::SigBit as_bit() const;
bool match(std::string pattern) const;
@@ -689,7 +715,6 @@ public:
std::vector<RTLIL::SigBit> to_sigbit_vector() const;
std::map<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_map(const RTLIL::SigSpec &other) const;
dict<RTLIL::SigBit, RTLIL::SigBit> to_sigbit_dict(const RTLIL::SigSpec &other) const;
- RTLIL::SigBit to_single_sigbit() const;
static bool parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str);
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str);
@@ -767,6 +792,7 @@ struct RTLIL::Design
int refcount_modules_;
dict<RTLIL::IdString, RTLIL::Module*> modules_;
+ std::vector<AST::AstNode*> verilog_packages;
std::vector<RTLIL::Selection> selection_stack;
dict<RTLIL::IdString, RTLIL::Selection> selection_vars;
@@ -777,6 +803,7 @@ struct RTLIL::Design
RTLIL::ObjRange<RTLIL::Module*> modules();
RTLIL::Module *module(RTLIL::IdString name);
+ RTLIL::Module *top_module();
bool has(RTLIL::IdString id) const {
return modules_.count(id) != 0;
@@ -785,6 +812,7 @@ struct RTLIL::Design
void add(RTLIL::Module *module);
RTLIL::Module *addModule(RTLIL::IdString name);
void remove(RTLIL::Module *module);
+ void rename(RTLIL::Module *module, RTLIL::IdString new_name);
void scratchpad_unset(std::string varname);
@@ -807,6 +835,14 @@ struct RTLIL::Design
bool selected_module(RTLIL::Module *mod) const;
bool selected_whole_module(RTLIL::Module *mod) const;
+ RTLIL::Selection &selection() {
+ return selection_stack.back();
+ }
+
+ const RTLIL::Selection &selection() const {
+ return selection_stack.back();
+ }
+
bool full_selection() const {
return selection_stack.back().full_selection;
}
@@ -831,18 +867,7 @@ struct RTLIL::Design
std::vector<RTLIL::Module*> selected_whole_modules_warn() const;
};
-#define RTLIL_ATTRIBUTE_MEMBERS \
- dict<RTLIL::IdString, RTLIL::Const> attributes; \
- void set_bool_attribute(RTLIL::IdString id) { \
- attributes[id] = RTLIL::Const(1); \
- } \
- bool get_bool_attribute(RTLIL::IdString id) const { \
- if (attributes.count(id) == 0) \
- return false; \
- return attributes.at(id).as_bool(); \
- }
-
-struct RTLIL::Module
+struct RTLIL::Module : public RTLIL::AttrObject
{
unsigned int hashidx_;
unsigned int hash() const { return hashidx_; }
@@ -866,7 +891,6 @@ public:
pool<RTLIL::IdString> avail_parameters;
dict<RTLIL::IdString, RTLIL::Memory*> memories;
dict<RTLIL::IdString, RTLIL::Process*> processes;
- RTLIL_ATTRIBUTE_MEMBERS
Module();
virtual ~Module();
@@ -933,25 +957,25 @@ public:
RTLIL::Cell* addNot (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addPos (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addNeg (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
-
+
RTLIL::Cell* addAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addXor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addXnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
-
+
RTLIL::Cell* addReduceAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addReduceOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addReduceXor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addReduceXnor (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addReduceBool (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
-
+
RTLIL::Cell* addShl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addShr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addSshl (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addSshr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addShift (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addShiftx (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
-
+
RTLIL::Cell* addLt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addLe (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addEq (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
@@ -960,24 +984,25 @@ public:
RTLIL::Cell* addNex (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addGe (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addGt (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
-
+
RTLIL::Cell* addAdd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addSub (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addMul (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addDiv (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addMod (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addPow (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool a_signed = false, bool b_signed = false);
-
+
RTLIL::Cell* addLogicNot (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addLogicAnd (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
RTLIL::Cell* addLogicOr (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y, bool is_signed = false);
-
+
RTLIL::Cell* addMux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y);
RTLIL::Cell* addPmux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s, RTLIL::SigSpec sig_y);
-
+
RTLIL::Cell* addSlice (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const offset);
RTLIL::Cell* addConcat (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y);
- RTLIL::Cell* addLut (RTLIL::IdString name, RTLIL::SigSpec sig_i, RTLIL::SigSpec sig_o, RTLIL::Const lut);
+ RTLIL::Cell* addLut (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_y, RTLIL::Const lut);
+ RTLIL::Cell* addTribuf (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_y);
RTLIL::Cell* addAssert (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_en);
RTLIL::Cell* addEquiv (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_y);
@@ -992,6 +1017,7 @@ public:
RTLIL::Cell* addDlatchsr (RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr,
RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true);
+ RTLIL::Cell* addBufGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y);
RTLIL::Cell* addNotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y);
RTLIL::Cell* addAndGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y);
RTLIL::Cell* addNandGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y);
@@ -1063,6 +1089,7 @@ public:
RTLIL::SigSpec Mux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s);
RTLIL::SigSpec Pmux (RTLIL::IdString name, RTLIL::SigSpec sig_a, RTLIL::SigSpec sig_b, RTLIL::SigSpec sig_s);
+ RTLIL::SigBit BufGate (RTLIL::IdString name, RTLIL::SigBit sig_a);
RTLIL::SigBit NotGate (RTLIL::IdString name, RTLIL::SigBit sig_a);
RTLIL::SigBit AndGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b);
RTLIL::SigBit NandGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b);
@@ -1077,7 +1104,7 @@ public:
RTLIL::SigBit Oai4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d);
};
-struct RTLIL::Wire
+struct RTLIL::Wire : public RTLIL::AttrObject
{
unsigned int hashidx_;
unsigned int hash() const { return hashidx_; }
@@ -1097,10 +1124,9 @@ public:
RTLIL::IdString name;
int width, start_offset, port_id;
bool port_input, port_output, upto;
- RTLIL_ATTRIBUTE_MEMBERS
};
-struct RTLIL::Memory
+struct RTLIL::Memory : public RTLIL::AttrObject
{
unsigned int hashidx_;
unsigned int hash() const { return hashidx_; }
@@ -1109,10 +1135,9 @@ struct RTLIL::Memory
RTLIL::IdString name;
int width, start_offset, size;
- RTLIL_ATTRIBUTE_MEMBERS
};
-struct RTLIL::Cell
+struct RTLIL::Cell : public RTLIL::AttrObject
{
unsigned int hashidx_;
unsigned int hash() const { return hashidx_; }
@@ -1132,7 +1157,6 @@ public:
RTLIL::IdString type;
dict<RTLIL::IdString, RTLIL::SigSpec> connections_;
dict<RTLIL::IdString, RTLIL::Const> parameters;
- RTLIL_ATTRIBUTE_MEMBERS
// access cell ports
bool hasPort(RTLIL::IdString portname) const;
@@ -1177,10 +1201,9 @@ struct RTLIL::CaseRule
RTLIL::CaseRule *clone() const;
};
-struct RTLIL::SwitchRule
+struct RTLIL::SwitchRule : public RTLIL::AttrObject
{
RTLIL::SigSpec signal;
- RTLIL_ATTRIBUTE_MEMBERS
std::vector<RTLIL::CaseRule*> cases;
~SwitchRule();
@@ -1199,10 +1222,9 @@ struct RTLIL::SyncRule
RTLIL::SyncRule *clone() const;
};
-struct RTLIL::Process
+struct RTLIL::Process : public RTLIL::AttrObject
{
RTLIL::IdString name;
- RTLIL_ATTRIBUTE_MEMBERS
RTLIL::CaseRule root_case;
std::vector<RTLIL::SyncRule*> syncs;
diff --git a/kernel/satgen.h b/kernel/satgen.h
index 2f5efe674..e118c1569 100644
--- a/kernel/satgen.h
+++ b/kernel/satgen.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -29,7 +29,37 @@
YOSYS_NAMESPACE_BEGIN
-typedef ezMiniSAT ezDefaultSAT;
+// defined in kernel/register.cc
+extern struct SatSolver *yosys_satsolver_list;
+extern struct SatSolver *yosys_satsolver;
+
+struct SatSolver
+{
+ string name;
+ SatSolver *next;
+ virtual ezSAT *create() = 0;
+
+ SatSolver(string name) : name(name) {
+ next = yosys_satsolver_list;
+ yosys_satsolver_list = this;
+ }
+
+ virtual ~SatSolver() {
+ auto p = &yosys_satsolver_list;
+ while (*p) {
+ if (*p == this)
+ *p = next;
+ else
+ p = &(*p)->next;
+ }
+ if (yosys_satsolver == this)
+ yosys_satsolver = yosys_satsolver_list;
+ }
+};
+
+struct ezSatPtr : public std::unique_ptr<ezSAT> {
+ ezSatPtr() : unique_ptr<ezSAT>(yosys_satsolver->create()) { }
+};
struct SatGen
{
@@ -38,6 +68,7 @@ struct SatGen
std::string prefix;
SigPool initial_state;
std::map<std::string, RTLIL::SigSpec> asserts_a, asserts_en;
+ std::map<std::string, RTLIL::SigSpec> assumes_a, assumes_en;
std::map<std::string, std::map<RTLIL::SigBit, int>> imported_signals;
bool ignore_div_by_zero;
bool model_undef;
@@ -131,6 +162,13 @@ struct SatGen
sig_en = asserts_en[pf];
}
+ void getAssumes(RTLIL::SigSpec &sig_a, RTLIL::SigSpec &sig_en, int timestep = -1)
+ {
+ std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
+ sig_a = assumes_a[pf];
+ sig_en = assumes_en[pf];
+ }
+
int importAsserts(int timestep = -1)
{
std::vector<int> check_bits, enable_bits;
@@ -145,6 +183,20 @@ struct SatGen
return ez->vec_reduce_and(ez->vec_or(check_bits, ez->vec_not(enable_bits)));
}
+ int importAssumes(int timestep = -1)
+ {
+ std::vector<int> check_bits, enable_bits;
+ std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
+ if (model_undef) {
+ check_bits = ez->vec_and(ez->vec_not(importUndefSigSpec(assumes_a[pf], timestep)), importDefSigSpec(assumes_a[pf], timestep));
+ enable_bits = ez->vec_and(ez->vec_not(importUndefSigSpec(assumes_en[pf], timestep)), importDefSigSpec(assumes_en[pf], timestep));
+ } else {
+ check_bits = importDefSigSpec(assumes_a[pf], timestep);
+ enable_bits = importDefSigSpec(assumes_en[pf], timestep);
+ }
+ return ez->vec_reduce_and(ez->vec_or(check_bits, ez->vec_not(enable_bits)));
+ }
+
int signals_eq(RTLIL::SigSpec lhs, RTLIL::SigSpec rhs, int timestep_lhs = -1, int timestep_rhs = -1)
{
if (timestep_rhs < 0)
@@ -928,7 +980,7 @@ struct SatGen
div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), ez->CONST_FALSE);
}
} else {
- int copy_a_bits = std::min(cell->getPort("\\A").size(), cell->getPort("\\B").size());
+ int copy_a_bits = min(cell->getPort("\\A").size(), cell->getPort("\\B").size());
div_zero_result.insert(div_zero_result.end(), a.begin(), a.begin() + copy_a_bits);
if (cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool())
div_zero_result.insert(div_zero_result.end(), y.size() - div_zero_result.size(), div_zero_result.back());
@@ -996,6 +1048,88 @@ struct SatGen
return true;
}
+ if (cell->type == "$sop")
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
+ int y = importDefSigSpec(cell->getPort("\\Y"), timestep).at(0);
+
+ int width = cell->getParam("\\WIDTH").as_int();
+ int depth = cell->getParam("\\DEPTH").as_int();
+
+ vector<State> table_raw = cell->getParam("\\TABLE").bits;
+ while (GetSize(table_raw) < 2*width*depth)
+ table_raw.push_back(State::S0);
+
+ vector<vector<int>> table(depth);
+
+ for (int i = 0; i < depth; i++)
+ for (int j = 0; j < width; j++)
+ {
+ bool pat0 = (table_raw[2*width*i + 2*j + 0] == State::S1);
+ bool pat1 = (table_raw[2*width*i + 2*j + 1] == State::S1);
+
+ if (pat0 && !pat1)
+ table.at(i).push_back(0);
+ else if (!pat0 && pat1)
+ table.at(i).push_back(1);
+ else
+ table.at(i).push_back(-1);
+ }
+
+ if (model_undef)
+ {
+ std::vector<int> products, undef_products;
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
+ int undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep).at(0);
+
+ for (int i = 0; i < depth; i++)
+ {
+ std::vector<int> cmp_a, cmp_ua, cmp_b;
+
+ for (int j = 0; j < width; j++)
+ if (table.at(i).at(j) >= 0) {
+ cmp_a.push_back(a.at(j));
+ cmp_ua.push_back(undef_a.at(j));
+ cmp_b.push_back(table.at(i).at(j) ? ez->CONST_TRUE : ez->CONST_FALSE);
+ }
+
+ std::vector<int> masked_a = ez->vec_or(cmp_a, cmp_ua);
+ std::vector<int> masked_b = ez->vec_or(cmp_b, cmp_ua);
+
+ int masked_eq = ez->vec_eq(masked_a, masked_b);
+ int any_undef = ez->expression(ezSAT::OpOr, cmp_ua);
+
+ undef_products.push_back(ez->AND(any_undef, masked_eq));
+ products.push_back(ez->AND(ez->NOT(any_undef), masked_eq));
+ }
+
+ int yy = ez->expression(ezSAT::OpOr, products);
+ ez->SET(undef_y, ez->AND(ez->NOT(yy), ez->expression(ezSAT::OpOr, undef_products)));
+ undefGating(y, yy, undef_y);
+ }
+ else
+ {
+ std::vector<int> products;
+
+ for (int i = 0; i < depth; i++)
+ {
+ std::vector<int> cmp_a, cmp_b;
+
+ for (int j = 0; j < width; j++)
+ if (table.at(i).at(j) >= 0) {
+ cmp_a.push_back(a.at(j));
+ cmp_b.push_back(table.at(i).at(j) ? ez->CONST_TRUE : ez->CONST_FALSE);
+ }
+
+ products.push_back(ez->vec_eq(cmp_a, cmp_b));
+ }
+
+ ez->SET(y, ez->expression(ezSAT::OpOr, products));
+ }
+
+ return true;
+ }
+
if (cell->type == "$fa")
{
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
@@ -1204,6 +1338,14 @@ struct SatGen
return true;
}
+ if (cell->type == "$assume")
+ {
+ std::string pf = prefix + (timestep == -1 ? "" : stringf("@%d:", timestep));
+ assumes_a[pf].append((*sigmap)(cell->getPort("\\A")));
+ assumes_en[pf].append((*sigmap)(cell->getPort("\\EN")));
+ return true;
+ }
+
// Unsupported internal cell types: $pow $lut
// .. and all sequential cells except $dff and $_DFF_[NP]_
return false;
diff --git a/kernel/sigtools.h b/kernel/sigtools.h
index f92a87dbb..4e97bb775 100644
--- a/kernel/sigtools.h
+++ b/kernel/sigtools.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -222,18 +222,7 @@ struct SigSet
struct SigMap
{
- struct bitDef_t : public std::pair<RTLIL::Wire*, int> {
- bitDef_t() : std::pair<RTLIL::Wire*, int>(NULL, 0) { }
- bitDef_t(const RTLIL::SigBit &bit) : std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset) { }
- unsigned int hash() const { return first->name.hash() + second; }
- };
-
- struct shared_bit_data_t {
- RTLIL::SigBit map_to;
- std::set<bitDef_t> bits;
- };
-
- dict<bitDef_t, shared_bit_data_t*> bits;
+ mfp<SigBit> database;
SigMap(RTLIL::Module *module = NULL)
{
@@ -241,119 +230,27 @@ struct SigMap
set(module);
}
- SigMap(const SigMap &other)
- {
- copy(other);
- }
-
- const SigMap &operator=(const SigMap &other)
- {
- copy(other);
- return *this;
- }
-
- void copy(const SigMap &other)
- {
- clear();
- for (auto &bit : other.bits) {
- bits[bit.first] = new shared_bit_data_t;
- bits[bit.first]->map_to = bit.second->map_to;
- bits[bit.first]->bits = bit.second->bits;
- }
- }
-
void swap(SigMap &other)
{
- bits.swap(other.bits);
- }
-
- ~SigMap()
- {
- clear();
+ database.swap(other.database);
}
void clear()
{
- std::set<shared_bit_data_t*> all_bd_ptr;
- for (auto &it : bits)
- all_bd_ptr.insert(it.second);
- for (auto bd_ptr : all_bd_ptr)
- delete bd_ptr;
- bits.clear();
+ database.clear();
}
void set(RTLIL::Module *module)
{
- clear();
+ int bitcount = 0;
for (auto &it : module->connections())
- add(it.first, it.second);
- }
+ bitcount += it.first.size();
- // internal helper function
- void register_bit(const RTLIL::SigBit &bit)
- {
- if (bit.wire && bits.count(bit) == 0) {
- shared_bit_data_t *bd = new shared_bit_data_t;
- bd->map_to = bit;
- bd->bits.insert(bit);
- bits[bit] = bd;
- }
- }
+ database.clear();
+ database.reserve(bitcount);
- // internal helper function
- void unregister_bit(const RTLIL::SigBit &bit)
- {
- if (bit.wire && bits.count(bit) > 0) {
- shared_bit_data_t *bd = bits[bit];
- bd->bits.erase(bit);
- if (bd->bits.size() == 0)
- delete bd;
- bits.erase(bit);
- }
- }
-
- // internal helper function
- void merge_bit(const RTLIL::SigBit &bit1, const RTLIL::SigBit &bit2)
- {
- log_assert(bit1.wire != NULL && bit2.wire != NULL);
-
- shared_bit_data_t *bd1 = bits[bit1];
- shared_bit_data_t *bd2 = bits[bit2];
- log_assert(bd1 != NULL && bd2 != NULL);
-
- if (bd1 == bd2)
- return;
-
- if (bd1->bits.size() < bd2->bits.size())
- {
- for (auto &bit : bd1->bits)
- bits[bit] = bd2;
- bd2->bits.insert(bd1->bits.begin(), bd1->bits.end());
- delete bd1;
- }
- else
- {
- bd1->map_to = bd2->map_to;
- for (auto &bit : bd2->bits)
- bits[bit] = bd1;
- bd1->bits.insert(bd2->bits.begin(), bd2->bits.end());
- delete bd2;
- }
- }
-
- // internal helper function
- void set_bit(const RTLIL::SigBit &bit1, const RTLIL::SigBit &bit2)
- {
- log_assert(bit1.wire != NULL);
- log_assert(bits.count(bit1) > 0);
- bits[bit1]->map_to = bit2;
- }
-
- // internal helper function
- void map_bit(RTLIL::SigBit &bit) const
- {
- if (bit.wire && bits.count(bit) > 0)
- bit = bits.at(bit)->map_to;
+ for (auto &it : module->connections())
+ add(it.first, it.second);
}
void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
@@ -362,45 +259,43 @@ struct SigMap
for (int i = 0; i < GetSize(from); i++)
{
- RTLIL::SigBit &bf = from[i];
- RTLIL::SigBit &bt = to[i];
+ int bfi = database.lookup(from[i]);
+ int bti = database.lookup(to[i]);
- if (bf.wire == NULL)
- continue;
+ const RTLIL::SigBit &bf = database[bfi];
+ const RTLIL::SigBit &bt = database[bti];
- register_bit(bf);
- register_bit(bt);
+ if (bf.wire || bt.wire)
+ {
+ database.imerge(bfi, bti);
- if (bt.wire != NULL)
- merge_bit(bf, bt);
- else
- set_bit(bf, bt);
+ if (bf.wire == nullptr)
+ database.ipromote(bfi);
+
+ if (bt.wire == nullptr)
+ database.ipromote(bti);
+ }
}
}
void add(RTLIL::SigSpec sig)
{
for (auto &bit : sig) {
- register_bit(bit);
- set_bit(bit, bit);
+ RTLIL::SigBit b = database.find(bit);
+ if (b.wire != nullptr)
+ database.promote(bit);
}
}
- void del(RTLIL::SigSpec sig)
- {
- for (auto &bit : sig)
- unregister_bit(bit);
- }
-
void apply(RTLIL::SigBit &bit) const
{
- map_bit(bit);
+ bit = database.find(bit);
}
void apply(RTLIL::SigSpec &sig) const
{
for (auto &bit : sig)
- map_bit(bit);
+ apply(bit);
}
RTLIL::SigBit operator()(RTLIL::SigBit bit) const
@@ -417,10 +312,19 @@ struct SigMap
RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
{
- RTLIL::SigSpec sig(wire);
+ SigSpec sig(wire);
apply(sig);
return sig;
}
+
+ RTLIL::SigSpec allbits() const
+ {
+ RTLIL::SigSpec sig;
+ for (auto &bit : database)
+ if (bit.wire != nullptr)
+ sig.append(bit);
+ return sig;
+ }
};
YOSYS_NAMESPACE_END
diff --git a/kernel/utils.h b/kernel/utils.h
index 2ec6182ea..8942905fe 100644
--- a/kernel/utils.h
+++ b/kernel/utils.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -186,7 +186,7 @@ struct TopoSort
active_stack.pop_back();
active_cells.erase(n);
}
-
+
marked_cells.insert(n);
sorted.push_back(n);
}
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index 530d78796..8da57fd4e 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -104,7 +104,7 @@ void yosys_banner()
log(" | |\n");
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
log(" | |\n");
- log(" | Copyright (C) 2012 - 2015 Clifford Wolf <clifford@clifford.at> |\n");
+ log(" | Copyright (C) 2012 - 2016 Clifford Wolf <clifford@clifford.at> |\n");
log(" | |\n");
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
@@ -124,6 +124,18 @@ void yosys_banner()
log("\n");
}
+int ceil_log2(int x)
+{
+ if (x <= 0)
+ return 0;
+
+ for (int i = 0; i < 32; i++)
+ if (((x-1) >> i) == 0)
+ return i;
+
+ log_abort();
+}
+
std::string stringf(const char *fmt, ...)
{
std::string string;
@@ -168,7 +180,7 @@ std::string vstringf(const char *fmt, va_list ap)
int readsome(std::istream &f, char *s, int n)
{
- int rc = f.readsome(s, n);
+ int rc = int(f.readsome(s, n));
// f.readsome() sometimes returns 0 on a non-empty stream..
if (rc == 0) {
@@ -182,13 +194,23 @@ int readsome(std::istream &f, char *s, int n)
return rc;
}
-std::string next_token(std::string &text, const char *sep)
+std::string next_token(std::string &text, const char *sep, bool long_strings)
{
size_t pos_begin = text.find_first_not_of(sep);
if (pos_begin == std::string::npos)
pos_begin = text.size();
+ if (long_strings && pos_begin != text.size() && text[pos_begin] == '"') {
+ string sep_string = sep;
+ for (size_t i = pos_begin+1; i < text.size(); i++)
+ if (text[i] == '"' && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) {
+ std::string token = text.substr(pos_begin, i-pos_begin+1);
+ text = text.substr(i+1);
+ return token;
+ }
+ }
+
size_t pos_end = text.find_first_of(sep, pos_begin);
if (pos_end == std::string::npos)
@@ -199,6 +221,26 @@ std::string next_token(std::string &text, const char *sep)
return token;
}
+std::vector<std::string> split_tokens(const std::string &text, const char *sep)
+{
+ std::vector<std::string> tokens;
+ std::string current_token;
+ for (char c : text) {
+ if (strchr(sep, c)) {
+ if (!current_token.empty()) {
+ tokens.push_back(current_token);
+ current_token.clear();
+ }
+ } else
+ current_token += c;
+ }
+ if (!current_token.empty()) {
+ tokens.push_back(current_token);
+ current_token.clear();
+ }
+ return tokens;
+}
+
// this is very similar to fnmatch(). the exact rules used by this
// function are:
//
@@ -376,6 +418,15 @@ bool check_file_exists(std::string filename, bool is_exec)
}
#endif
+bool is_absolute_path(std::string filename)
+{
+#ifdef _WIN32
+ return filename[0] == '/' || filename[0] == '\\' || (filename[0] != 0 && filename[1] == ':');
+#else
+ return filename[0] == '/';
+#endif
+}
+
void remove_directory(std::string dirname)
{
#ifdef _WIN32
@@ -496,6 +547,14 @@ const char *create_prompt(RTLIL::Design *design, int recursion_counter)
return buffer;
}
+void rewrite_filename(std::string &filename)
+{
+ if (filename.substr(0, 1) == "\"" && filename.substr(GetSize(filename)-1) == "\"")
+ filename = filename.substr(1, GetSize(filename)-2);
+ if (filename.substr(0, 2) == "+/")
+ filename = proc_share_dirname() + filename.substr(2);
+}
+
#ifdef YOSYS_ENABLE_TCL
static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *argv[])
{
@@ -549,7 +608,7 @@ struct TclPass : public Pass {
log("The tcl command 'yosys -import' can be used to import all yosys\n");
log("commands directly as tcl commands to the tcl shell. The yosys\n");
log("command 'proc' is wrapped using the tcl command 'procs' in order\n");
- log("to avoid a name collision with the tcl builting command 'proc'.\n");
+ log("to avoid a name collision with the tcl builtin command 'proc'.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
@@ -619,26 +678,38 @@ std::string proc_self_dirname()
#error Dont know how to determine process executable base path!
#endif
+#ifdef EMSCRIPTEN
+std::string proc_share_dirname()
+{
+ return "/share";
+}
+#else
std::string proc_share_dirname()
{
std::string proc_self_path = proc_self_dirname();
-#ifdef _WIN32
+# ifdef _WIN32
std::string proc_share_path = proc_self_path + "share\\";
if (check_file_exists(proc_share_path, true))
return proc_share_path;
proc_share_path = proc_self_path + "..\\share\\";
if (check_file_exists(proc_share_path, true))
return proc_share_path;
-#else
+# else
std::string proc_share_path = proc_self_path + "share/";
if (check_file_exists(proc_share_path, true))
return proc_share_path;
proc_share_path = proc_self_path + "../share/yosys/";
if (check_file_exists(proc_share_path, true))
return proc_share_path;
-#endif
+# ifdef YOSYS_DATDIR
+ proc_share_path = YOSYS_DATDIR "/";
+ if (check_file_exists(proc_share_path, true))
+ return proc_share_path;
+# endif
+# endif
log_error("proc_share_dirname: unable to determine share/ directory!\n");
}
+#endif
bool fgetline(FILE *f, std::string &buffer)
{
@@ -664,6 +735,9 @@ static void handle_label(std::string &command, bool &from_to_active, const std::
while (pos < GetSize(command) && (command[pos] == ' ' || command[pos] == '\t'))
pos++;
+ if (pos < GetSize(command) && command[pos] == '#')
+ return;
+
while (pos < GetSize(command) && command[pos] != ' ' && command[pos] != '\t' && command[pos] != '\r' && command[pos] != '\n')
label += command[pos++];
@@ -689,6 +763,10 @@ void run_frontend(std::string filename, std::string command, std::string *backen
command = "verilog";
else if (filename.size() > 2 && filename.substr(filename.size()-3) == ".sv")
command = "verilog -sv";
+ else if (filename.size() > 2 && filename.substr(filename.size()-4) == ".vhd")
+ command = "vhdl";
+ else if (filename.size() > 4 && filename.substr(filename.size()-5) == ".blif")
+ command = "blif";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
command = "ilang";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".ys")
@@ -802,6 +880,10 @@ void run_backend(std::string filename, std::string command, RTLIL::Design *desig
command = "ilang";
else if (filename.size() > 5 && filename.substr(filename.size()-5) == ".blif")
command = "blif";
+ else if (filename.size() > 5 && filename.substr(filename.size()-5) == ".edif")
+ command = "edif";
+ else if (filename.size() > 5 && filename.substr(filename.size()-5) == ".json")
+ command = "json";
else if (filename == "-")
command = "ilang";
else if (filename.empty())
@@ -1018,8 +1100,8 @@ struct HistoryPass : public Pass {
} HistoryPass;
#endif
-struct ScriptPass : public Pass {
- ScriptPass() : Pass("script", "execute commands from script file") { }
+struct ScriptCmdPass : public Pass {
+ ScriptCmdPass() : Pass("script", "execute commands from script file") { }
virtual void help() {
log("\n");
log(" script <filename> [<from_label>:<to_label>]\n");
@@ -1045,7 +1127,7 @@ struct ScriptPass : public Pass {
else
extra_args(args, 2, design, false);
}
-} ScriptPass;
+} ScriptCmdPass;
YOSYS_NAMESPACE_END
diff --git a/kernel/yosys.h b/kernel/yosys.h
index 47275ecd4..0df750a13 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -2,11 +2,11 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
+ *
* 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
@@ -41,6 +41,7 @@
#include <map>
#include <set>
+#include <tuple>
#include <vector>
#include <string>
#include <algorithm>
@@ -49,6 +50,8 @@
#include <unordered_set>
#include <initializer_list>
#include <stdexcept>
+#include <memory>
+#include <cmath>
#include <sstream>
#include <fstream>
@@ -89,9 +92,9 @@
# define mkdir _mkdir
# define popen _popen
# define pclose _pclose
-# define PATH_MAX MAX_PATH
# ifndef __MINGW32__
+# define PATH_MAX MAX_PATH
# define isatty _isatty
# define fileno _fileno
# endif
@@ -137,8 +140,27 @@ YOSYS_NAMESPACE_BEGIN
using std::vector;
using std::string;
+using std::tuple;
using std::pair;
+using std::make_tuple;
+using std::make_pair;
+using std::min;
+using std::max;
+
+// A primitive shared string implementation that does not
+// move its .c_str() when the object is copied or moved.
+struct shared_str {
+ std::shared_ptr<string> content;
+ shared_str() { }
+ shared_str(string s) { content = std::shared_ptr<string>(new string(s)); }
+ shared_str(const char *s) { content = std::shared_ptr<string>(new string(s)); }
+ const char *c_str() const { return content->c_str(); }
+ const string &str() const { return *content; }
+ bool operator==(const shared_str &other) const { return *content == *other.content; }
+ unsigned int hash() const { return hashlib::hash_ops<std::string>::hash(*content); }
+};
+
using hashlib::mkhash;
using hashlib::mkhash_init;
using hashlib::mkhash_add;
@@ -150,6 +172,7 @@ using hashlib::hash_obj_ops;
using hashlib::dict;
using hashlib::idict;
using hashlib::pool;
+using hashlib::mfp;
namespace RTLIL {
struct IdString;
@@ -200,15 +223,18 @@ extern bool memhasher_active;
inline void memhasher() { if (memhasher_active) memhasher_do(); }
void yosys_banner();
+int ceil_log2(int x);
std::string stringf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 1, 2));
std::string vstringf(const char *fmt, va_list ap);
int readsome(std::istream &f, char *s, int n);
-std::string next_token(std::string &text, const char *sep = " \t\r\n");
+std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false);
+std::vector<std::string> split_tokens(const std::string &text, const char *sep = " \t\r\n");
bool patmatch(const char *pattern, const char *string);
int run_command(const std::string &command, std::function<void(const std::string&)> process_line = std::function<void(const std::string&)>());
std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX");
std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX");
bool check_file_exists(std::string filename, bool is_exec = false);
+bool is_absolute_path(std::string filename);
void remove_directory(std::string dirname);
template<typename T> int GetSize(const T &obj) { return obj.size(); }
@@ -226,6 +252,8 @@ YOSYS_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
using RTLIL::State;
+using RTLIL::SigChunk;
+using RTLIL::SigSig;
namespace hashlib {
template<> struct hash_ops<RTLIL::State> : hash_ops<int> {};
@@ -252,6 +280,7 @@ RTLIL::Design *yosys_get_design();
std::string proc_self_dirname();
std::string proc_share_dirname();
const char *create_prompt(RTLIL::Design *design, int recursion_counter);
+void rewrite_filename(std::string &filename);
void run_pass(std::string command, RTLIL::Design *design = nullptr);
void run_frontend(std::string filename, std::string command, std::string *backend_command, std::string *from_to_label = nullptr, RTLIL::Design *design = nullptr);