3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-23 09:05:32 +00:00

initial import

This commit is contained in:
Clifford Wolf 2013-01-05 11:13:26 +01:00
commit 7764d0ba1d
481 changed files with 54634 additions and 0 deletions

143
kernel/bitpattern.h Normal file
View file

@ -0,0 +1,143 @@
/*
* 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 BITPATTERN_H
#define BITPATTERN_H
#include "kernel/log.h"
#include "kernel/rtlil.h"
struct BitPatternPool
{
int width;
typedef std::vector<RTLIL::State> bits_t;
std::set<bits_t> pool;
BitPatternPool(RTLIL::SigSpec sig)
{
width = sig.width;
if (width > 0) {
std::vector<RTLIL::State> pattern(width);
sig.optimize();
for (int i = 0; i < width; i++) {
RTLIL::SigSpec s = sig.extract(i, 1);
s.optimize();
assert(s.chunks.size() == 1);
if (s.chunks[0].wire == NULL && s.chunks[0].data.bits[0] <= RTLIL::State::S1)
pattern[i] = s.chunks[0].data.bits[0];
else
pattern[i] = RTLIL::State::Sa;
}
pool.insert(pattern);
}
}
BitPatternPool(int width)
{
this->width = width;
if (width > 0) {
std::vector<RTLIL::State> pattern(width);
for (int i = 0; i < width; i++)
pattern[i] = RTLIL::State::Sa;
pool.insert(pattern);
}
}
bits_t sig2bits(RTLIL::SigSpec sig)
{
sig.optimize();
assert(sig.is_fully_const());
assert(sig.chunks.size() == 1);
bits_t bits = sig.chunks[0].data.bits;
for (auto &b : bits)
if (b > RTLIL::State::S1)
b = RTLIL::State::Sa;
return bits;
}
bool match(bits_t a, bits_t b)
{
assert(int(a.size()) == width);
assert(int(b.size()) == width);
for (int i = 0; i < width; i++)
if (a[i] <= RTLIL::State::S1 && b[i] <= RTLIL::State::S1 && a[i] != b[i])
return false;
return true;
}
bool has_any(RTLIL::SigSpec sig)
{
bits_t bits = sig2bits(sig);
for (auto &it : pool)
if (match(it, bits))
return true;
return false;
}
bool has_all(RTLIL::SigSpec sig)
{
bits_t bits = sig2bits(sig);
for (auto &it : pool)
if (match(it, bits)) {
for (int i = 0; i < width; i++)
if (bits[i] > RTLIL::State::S1 && it[i] <= RTLIL::State::S1)
goto next_pool_entry;
return true;
next_pool_entry:;
}
return false;
}
bool take(RTLIL::SigSpec sig)
{
bool status = false;
bits_t bits = sig2bits(sig);
std::vector<bits_t> pattern_list;
for (auto &it : pool)
if (match(it, bits))
pattern_list.push_back(it);
for (auto pattern : pattern_list) {
pool.erase(pattern);
for (int i = 0; i < width; i++) {
if (pattern[i] != RTLIL::State::Sa || bits[i] == RTLIL::State::Sa)
continue;
bits_t new_pattern = pattern;
new_pattern[i] = bits[i] == RTLIL::State::S1 ? RTLIL::State::S0 : RTLIL::State::S1;
pool.insert(new_pattern);
}
status = true;
}
return status;
}
bool take_all()
{
if (pool.empty())
return false;
pool.clear();
return true;
}
bool empty()
{
return pool.empty();
}
};
#endif

392
kernel/calc.cc Normal file
View file

@ -0,0 +1,392 @@
/*
* 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/rtlil.h"
#include "bigint/BigIntegerLibrary.hh"
#include <assert.h>
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;
}
return result;
}
static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_bit_pos)
{
BigUnsigned mag = val.getMagnitude();
RTLIL::Const result(0, result_len);
if (!mag.isZero())
{
if (val.getSign() < 0)
{
mag--;
for (int i = 0; i < result_len; i++)
result.bits[i] = mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1;
}
else
{
for (int i = 0; i < result_len; i++)
result.bits[i] = mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0;
}
}
if (undef_bit_pos >= 0)
for (int i = undef_bit_pos; i < result_len; i++)
result.bits[i] = RTLIL::State::Sx;
return result;
}
static RTLIL::State logic_and(RTLIL::State a, RTLIL::State b)
{
if (a == RTLIL::State::S0) return RTLIL::State::S0;
if (b == RTLIL::State::S0) return RTLIL::State::S0;
if (a != RTLIL::State::S1) return RTLIL::State::Sx;
if (b != RTLIL::State::S1) return RTLIL::State::Sx;
return RTLIL::State::S1;
}
static RTLIL::State logic_or(RTLIL::State a, RTLIL::State b)
{
if (a == RTLIL::State::S1) return RTLIL::State::S1;
if (b == RTLIL::State::S1) return RTLIL::State::S1;
if (a != RTLIL::State::S0) return RTLIL::State::Sx;
if (b != RTLIL::State::S0) return RTLIL::State::Sx;
return RTLIL::State::S0;
}
static RTLIL::State logic_xor(RTLIL::State a, RTLIL::State b)
{
if (a != RTLIL::State::S0 && a != RTLIL::State::S1) return RTLIL::State::Sx;
if (b != RTLIL::State::S0 && b != RTLIL::State::S1) return RTLIL::State::Sx;
return a != b ? RTLIL::State::S1 : RTLIL::State::S0;
}
static RTLIL::State logic_xnor(RTLIL::State a, RTLIL::State b)
{
if (a != RTLIL::State::S0 && a != RTLIL::State::S1) return RTLIL::State::Sx;
if (b != RTLIL::State::S0 && b != RTLIL::State::S1) return RTLIL::State::Sx;
return a == b ? RTLIL::State::S1 : RTLIL::State::S0;
}
RTLIL::Const RTLIL::const_not(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int result_len)
{
if (result_len < 0)
result_len = arg1.bits.size();
RTLIL::Const result(RTLIL::State::Sx, result_len);
for (size_t i = 0; i < size_t(result_len); i++) {
if (i >= arg1.bits.size())
result.bits[i] = RTLIL::State::S0;
else if (arg1.bits[i] == RTLIL::State::S0)
result.bits[i] = RTLIL::State::S1;
else if (arg1.bits[i] == RTLIL::State::S1)
result.bits[i] = RTLIL::State::S0;
}
return result;
}
static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL::State),
const RTLIL::Const &arg1, const RTLIL::Const &arg2, int result_len = -1)
{
if (result_len < 0)
result_len = std::max(arg1.bits.size(), arg2.bits.size());
RTLIL::Const result(RTLIL::State::Sx, result_len);
for (size_t i = 0; i < size_t(result_len); i++) {
RTLIL::State a = i < arg1.bits.size() ? arg1.bits[i] : RTLIL::State::S0;
RTLIL::State b = i < arg2.bits.size() ? arg2.bits[i] : RTLIL::State::S0;
result.bits[i] = logic_func(a, b);
}
return result;
}
RTLIL::Const RTLIL::const_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return logic_wrapper(logic_and, arg1, arg2, result_len);
}
RTLIL::Const RTLIL::const_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return logic_wrapper(logic_or, arg1, arg2, result_len);
}
RTLIL::Const RTLIL::const_xor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return logic_wrapper(logic_xor, arg1, arg2, result_len);
}
RTLIL::Const RTLIL::const_xnor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return logic_wrapper(logic_xnor, arg1, arg2, result_len);
}
static RTLIL::Const logic_reduce_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL::State), const RTLIL::Const &arg1)
{
RTLIL::State temp = RTLIL::State::S0;
for (size_t i = 0; i < arg1.bits.size(); i++)
temp = logic_func(temp, arg1.bits[i]);
return RTLIL::Const(temp);
}
RTLIL::Const RTLIL::const_reduce_and(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int)
{
return logic_reduce_wrapper(logic_and, arg1);
}
RTLIL::Const RTLIL::const_reduce_or(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int)
{
return logic_reduce_wrapper(logic_or, arg1);
}
RTLIL::Const RTLIL::const_reduce_xor(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int)
{
return logic_reduce_wrapper(logic_xor, arg1);
}
RTLIL::Const RTLIL::const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int)
{
return logic_reduce_wrapper(logic_xnor, arg1);
}
RTLIL::Const RTLIL::const_reduce_bool(const RTLIL::Const &arg1, const RTLIL::Const&, bool, bool, int)
{
return logic_reduce_wrapper(logic_or, arg1);
}
RTLIL::Const RTLIL::const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int)
{
int undef_bit_pos_a = -1;
BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
if (a.isZero()) {
if (undef_bit_pos_a >= 0)
return RTLIL::Const(RTLIL::State::Sx);
return RTLIL::Const(RTLIL::State::S1);
}
return RTLIL::Const(RTLIL::State::S0);
}
RTLIL::Const RTLIL::const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos_a = -1, undef_bit_pos_b = -1;
BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
BigInteger b = const2big(arg2, signed2, undef_bit_pos_b);
if (a.isZero() || b.isZero()) {
if (undef_bit_pos_a >= 0 && undef_bit_pos_b >= 0)
return RTLIL::Const(RTLIL::State::Sx);
return RTLIL::Const(RTLIL::State::S0);
}
return RTLIL::Const(RTLIL::State::S1);
}
RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos_a = -1, undef_bit_pos_b = -1;
BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
BigInteger b = const2big(arg2, signed2, undef_bit_pos_b);
if (a.isZero() && b.isZero()) {
if (undef_bit_pos_a >= 0 || undef_bit_pos_b >= 0)
return RTLIL::Const(RTLIL::State::Sx);
return RTLIL::Const(RTLIL::State::S0);
}
return RTLIL::Const(RTLIL::State::S1);
}
static RTLIL::Const const_shift(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool sign_ext, int direction, int result_len)
{
int undef_bit_pos = -1;
BigInteger offset = const2big(arg2, false, undef_bit_pos) * direction;
if (result_len < 0)
result_len = arg1.bits.size();
RTLIL::Const result(RTLIL::State::Sx, result_len);
if (undef_bit_pos >= 0)
return result;
for (int i = 0; i < result_len; i++) {
BigInteger pos = BigInteger(i) + offset;
if (pos < 0)
result.bits[i] = RTLIL::State::S0;
else if (pos >= arg1.bits.size())
result.bits[i] = sign_ext ? arg1.bits.back() : RTLIL::State::S0;
else
result.bits[i] = arg1.bits[pos.toInt()];
}
return result;
}
RTLIL::Const RTLIL::const_shl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return const_shift(arg1, arg2, false, -1, result_len);
}
RTLIL::Const RTLIL::const_shr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return const_shift(arg1, arg2, false, +1, result_len);
}
RTLIL::Const RTLIL::const_sshl(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return const_shift(arg1, arg2, true, -1, result_len);
}
RTLIL::Const RTLIL::const_sshr(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool, bool, int result_len)
{
return const_shift(arg1, arg2, true, +1, result_len);
}
RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos);
return RTLIL::Const(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
}
RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos);
return RTLIL::Const(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
}
RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) == const2big(arg2, signed2, undef_bit_pos);
return RTLIL::Const(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
}
RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) != const2big(arg2, signed2, undef_bit_pos);
return RTLIL::Const(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
}
RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos);
return RTLIL::Const(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
}
RTLIL::Const RTLIL::const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int)
{
int undef_bit_pos = -1;
bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos);
return RTLIL::Const(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
}
RTLIL::Const RTLIL::const_add(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);
}
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);
}
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));
}
RTLIL::Const RTLIL::const_div(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));
}
RTLIL::Const RTLIL::const_mod(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));
}
RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
{
int undef_bit_pos = -1;
BigInteger a = const2big(arg1, signed1, undef_bit_pos);
BigInteger b = const2big(arg2, signed2, undef_bit_pos);
BigInteger y = 1;
if (b < 0 || a == 0) {
y = 0;
} else {
while (b > 0) {
y = y * a;
if (y.getLength() > 0x10000) {
undef_bit_pos = 0;
break;
}
b--;
}
}
return big2const(y, result_len >= 0 ? result_len : std::max(arg1.bits.size(), arg2.bits.size()), std::min(undef_bit_pos, 0));
}
RTLIL::Const RTLIL::const_pos(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
{
RTLIL::Const zero(RTLIL::State::S0, 1);
return RTLIL::const_add(zero, arg1, false, signed1, result_len);
}
RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
{
RTLIL::Const zero(RTLIL::State::S0, 1);
return RTLIL::const_sub(zero, arg1, false, signed1, result_len);
}

210
kernel/celltypes.h Normal file
View file

@ -0,0 +1,210 @@
/*
* 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 CELLTYPES_H
#define CELLTYPES_H
#include <set>
#include <string>
#include <stdlib.h>
struct CellTypes
{
std::set<std::string> cell_types;
void setup_internals()
{
cell_types.insert("$not");
cell_types.insert("$pos");
cell_types.insert("$neg");
cell_types.insert("$and");
cell_types.insert("$or");
cell_types.insert("$xor");
cell_types.insert("$xnor");
cell_types.insert("$reduce_and");
cell_types.insert("$reduce_or");
cell_types.insert("$reduce_xor");
cell_types.insert("$reduce_xnor");
cell_types.insert("$reduce_bool");
cell_types.insert("$shl");
cell_types.insert("$shr");
cell_types.insert("$sshl");
cell_types.insert("$sshr");
cell_types.insert("$lt");
cell_types.insert("$le");
cell_types.insert("$eq");
cell_types.insert("$ne");
cell_types.insert("$ge");
cell_types.insert("$gt");
cell_types.insert("$add");
cell_types.insert("$sub");
cell_types.insert("$mul");
cell_types.insert("$div");
cell_types.insert("$mod");
cell_types.insert("$pow");
cell_types.insert("$logic_not");
cell_types.insert("$logic_and");
cell_types.insert("$logic_or");
cell_types.insert("$mux");
cell_types.insert("$pmux");
cell_types.insert("$safe_pmux");
}
void setup_internals_mem()
{
cell_types.insert("$dff");
cell_types.insert("$adff");
cell_types.insert("$memrd");
cell_types.insert("$memwr");
cell_types.insert("$mem");
cell_types.insert("$fsm");
}
void setup_stdcells()
{
cell_types.insert("$_INV_");
cell_types.insert("$_AND_");
cell_types.insert("$_OR_");
cell_types.insert("$_XOR_");
cell_types.insert("$_MUX_");
}
void setup_stdcells_mem()
{
cell_types.insert("$_DFF_N_");
cell_types.insert("$_DFF_P_");
cell_types.insert("$_DFF_NN0_");
cell_types.insert("$_DFF_NN1_");
cell_types.insert("$_DFF_NP0_");
cell_types.insert("$_DFF_NP1_");
cell_types.insert("$_DFF_PN0_");
cell_types.insert("$_DFF_PN1_");
cell_types.insert("$_DFF_PP0_");
cell_types.insert("$_DFF_PP1_");
}
void clear()
{
cell_types.clear();
}
bool cell_known(std::string type)
{
return cell_types.count(type) > 0;
}
bool cell_output(std::string type, std::string port)
{
if (!cell_known(type))
return false;
if (port == "\\Y" || port == "\\Q" || port == "\\RD_DATA")
return true;
if (type == "$memrd" && port == "\\DATA")
return true;
if (type == "$fsm" && port == "\\CTRL_OUT")
return true;
return false;
}
bool cell_input(std::string type, std::string port)
{
if (!cell_known(type))
return false;
return !cell_output(type, port);
}
static RTLIL::Const eval(std::string type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
{
#define HANDLE_CELL_TYPE(_t) if (type == "$" #_t) return const_ ## _t(arg1, arg2, signed1, signed2, result_len);
HANDLE_CELL_TYPE(not)
HANDLE_CELL_TYPE(and)
HANDLE_CELL_TYPE(or)
HANDLE_CELL_TYPE(xor)
HANDLE_CELL_TYPE(xnor)
HANDLE_CELL_TYPE(reduce_and)
HANDLE_CELL_TYPE(reduce_or)
HANDLE_CELL_TYPE(reduce_xor)
HANDLE_CELL_TYPE(reduce_xnor)
HANDLE_CELL_TYPE(reduce_bool)
HANDLE_CELL_TYPE(logic_not)
HANDLE_CELL_TYPE(logic_and)
HANDLE_CELL_TYPE(logic_or)
HANDLE_CELL_TYPE(shl)
HANDLE_CELL_TYPE(shr)
HANDLE_CELL_TYPE(sshl)
HANDLE_CELL_TYPE(sshr)
HANDLE_CELL_TYPE(lt)
HANDLE_CELL_TYPE(le)
HANDLE_CELL_TYPE(eq)
HANDLE_CELL_TYPE(ne)
HANDLE_CELL_TYPE(ge)
HANDLE_CELL_TYPE(gt)
HANDLE_CELL_TYPE(add)
HANDLE_CELL_TYPE(sub)
HANDLE_CELL_TYPE(mul)
HANDLE_CELL_TYPE(div)
HANDLE_CELL_TYPE(mod)
HANDLE_CELL_TYPE(pow)
HANDLE_CELL_TYPE(pos)
HANDLE_CELL_TYPE(neg)
#undef HANDLE_CELL_TYPE
if (type == "$_INV_")
return const_not(arg1, arg2, false, false, 1);
if (type == "$_AND_")
return const_and(arg1, arg2, false, false, 1);
if (type == "$_OR_")
return const_or(arg1, arg2, false, false, 1);
if (type == "$_XOR_")
return const_xor(arg1, arg2, false, false, 1);
assert(!"Called CellType.eval() with unsupported cell type!");
abort();
}
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2)
{
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;
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
}
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &sel)
{
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$safe_pmux" || cell->type == "$_MUX_") {
RTLIL::Const ret = arg1;
for (size_t i = 0; i < sel.bits.size(); i++)
if (sel.bits[i] == RTLIL::State::S1) {
std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
ret = RTLIL::Const(bits);
}
return ret;
}
assert(sel.bits.size() == 0);
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;
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
}
};
#endif

198
kernel/consteval.h Normal file
View file

@ -0,0 +1,198 @@
/*
* 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 CONSTEVAL_H
#define CONSTEVAL_H
#include "kernel/rtlil.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
struct ConstEval
{
RTLIL::Module *module;
SigMap assign_map;
SigMap values_map;
SigPool stop_signals;
SigSet<RTLIL::Cell*> sig2driver;
std::set<RTLIL::Cell*> busy;
std::vector<SigMap> stack;
ConstEval(RTLIL::Module *module) : module(module), assign_map(module)
{
CellTypes ct;
ct.setup_internals();
ct.setup_stdcells();
for (auto &it : module->cells) {
if (!ct.cell_known(it.second->type))
continue;
for (auto &it2 : it.second->connections)
if (ct.cell_output(it.second->type, it2.first))
sig2driver.insert(assign_map(it2.second), it.second);
}
}
void clear()
{
values_map.clear();
stop_signals.clear();
}
void push()
{
stack.push_back(values_map);
}
void pop()
{
values_map.swap(stack.back());
stack.pop_back();
}
void set(RTLIL::SigSpec sig, RTLIL::Const value)
{
assign_map.apply(sig);
#ifndef NDEBUG
RTLIL::SigSpec current_val = values_map(sig);
current_val.expand();
for (size_t i = 0; i < current_val.chunks.size(); i++) {
RTLIL::SigChunk &chunk = current_val.chunks[i];
assert(chunk.wire != NULL || chunk.data.bits[0] == value.bits[i]);
}
#endif
values_map.add(sig, RTLIL::SigSpec(value));
}
void stop(RTLIL::SigSpec sig)
{
assign_map.apply(sig);
stop_signals.add(sig);
}
bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef)
{
RTLIL::SigSpec sig_a, sig_b, sig_s, sig_y;
bool ignore_sig_a = false, ignore_sig_b = false;
int sig_b_shift = -1;
assert(cell->connections.count("\\Y") > 0);
sig_y = values_map(assign_map(cell->connections["\\Y"]));
if (sig_y.is_fully_const())
return true;
if (cell->connections.count("\\S") > 0) {
sig_s = cell->connections["\\S"];
if (!eval(sig_s, undef, cell))
return false;
}
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$safe_pmux" || cell->type == "$_MUX_") {
bool found_collision = false;
for (int i = 0; i < sig_s.width; i++)
if (sig_s.extract(i, 1).as_bool()) {
if (sig_b_shift >= 0)
found_collision = true;
sig_b_shift = i;
ignore_sig_a = true;
if (cell->type != "$safe_pmux")
break;
}
if (found_collision) {
sig_b_shift = -1;
ignore_sig_a = false;
}
if (sig_b_shift < 0)
ignore_sig_b = true;
}
if (!ignore_sig_a && cell->connections.count("\\A") > 0) {
sig_a = cell->connections["\\A"];
if (!eval(sig_a, undef, cell))
return false;
}
if (!ignore_sig_b && cell->connections.count("\\B") > 0) {
sig_b = cell->connections["\\B"];
if (sig_b_shift >= 0)
sig_b = sig_b.extract(sig_y.width*sig_b_shift, sig_y.width);
if (!eval(sig_b, undef, cell))
return false;
}
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$safe_pmux" || cell->type == "$_MUX_")
set(sig_y, sig_s.as_bool() ? sig_b.as_const() : sig_a.as_const());
else
set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const()));
return true;
}
bool eval(RTLIL::SigSpec &sig, RTLIL::SigSpec &undef, RTLIL::Cell *busy_cell = NULL)
{
assign_map.apply(sig);
values_map.apply(sig);
if (sig.is_fully_const())
return true;
if (stop_signals.check_any(sig)) {
undef = stop_signals.extract(sig);
return false;
}
if (busy_cell) {
if (busy.count(busy_cell) > 0) {
undef = sig;
return false;
}
busy.insert(busy_cell);
}
std::set<RTLIL::Cell*> driver_cells;
sig2driver.find(sig, driver_cells);
for (auto cell : driver_cells) {
if (!eval(cell, undef)) {
if (busy_cell)
busy.erase(busy_cell);
return false;
}
}
if (busy_cell)
busy.erase(busy_cell);
values_map.apply(sig);
if (sig.is_fully_const())
return true;
for (size_t i = 0; i < sig.chunks.size(); i++)
if (sig.chunks[i].wire != NULL)
undef.append(sig.chunks[i]);
return false;
}
bool eval(RTLIL::SigSpec &sig)
{
RTLIL::SigSpec undef;
return eval(sig, undef);
}
};
#endif

253
kernel/driver.cc Normal file
View file

@ -0,0 +1,253 @@
/*
* 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 <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/log.h"
#include <string.h>
#include <unistd.h>
static void run_frontend(std::string filename, std::string command, RTLIL::Design *design, std::string *backend_command)
{
if (command == "auto") {
if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
command = "verilog";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
command = "ilang";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".ys")
command = "script";
else if (filename == "-")
command = "ilang";
else
log_error("Can't guess frontend for input file `%s' (missing -f option)!\n", filename.c_str());
}
if (command == "script") {
log("\n-- Executing script file `%s' --\n", filename.c_str());
FILE *f = fopen(filename.c_str(), "r");
if (f == NULL)
log_error("Can;t open script file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
char buffer[4096];
while (fgets(buffer, 4096, f) != NULL) {
Pass::call(design, buffer);
design->check();
}
fclose(f);
if (backend_command != NULL && *backend_command == "auto")
*backend_command = "";
return;
}
if (filename == "-") {
log("\n-- Parsing stdin using frontend `%s' --\n", command.c_str());
} else {
log("\n-- Parsing `%s' using frontend `%s' --\n", filename.c_str(), command.c_str());
}
Frontend::frontend_call(design, NULL, filename, command);
design->check();
}
static void run_pass(std::string command, RTLIL::Design *design)
{
log("\n-- Running pass `%s' --\n", command.c_str());
Pass::call(design, command);
design->check();
}
static void run_backend(std::string filename, std::string command, RTLIL::Design *design)
{
if (command == "auto") {
if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
command = "verilog";
else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
command = "ilang";
else if (filename == "-")
command = "ilang";
else
log_error("Can't guess frontend for input file `%s' (missing -f option)!\n", filename.c_str());
}
if (filename == "-") {
log("\n-- Writing to stdout using backend `%s' --\n", command.c_str());
} else {
log("\n-- Writing to `%s' using backend `%s' --\n", filename.c_str(), command.c_str());
}
Backend::backend_call(design, NULL, filename, command);
design->check();
}
static char *readline_cmd_generator(const char *text, int state)
{
static std::map<std::string, Pass*>::iterator it;
static int len;
if (!state) {
it = REGISTER_INTERN::pass_register.begin();
len = strlen(text);
}
for (; it != REGISTER_INTERN::pass_register.end(); it++) {
if (it->first.substr(0, len) == text)
return strdup((it++)->first.c_str());
}
return NULL;
}
static char **readline_completion(const char *text, int start, int)
{
if (start == 0)
return rl_completion_matches(text, readline_cmd_generator);
return NULL;
}
static const char *create_prompt(RTLIL::Design *design)
{
static char buffer[100];
std::string str = "\nyosys";
if (!design->selected_active_module.empty())
str += stringf(" [%s]", design->selected_active_module.c_str());
if (!design->selection_stack.back().full_selection) {
if (design->selected_active_module.empty())
str += "*";
else if (design->selection_stack.back().selected_modules.size() != 1 || design->selection_stack.back().selected_members.size() != 0 ||
design->selection_stack.back().selected_modules.count(design->selected_active_module) == 0)
str += "*";
}
snprintf(buffer, 100, "%s> ", str.c_str());
return buffer;
}
int main(int argc, char **argv)
{
std::string frontend_command = "auto";
std::string backend_command = "auto";
std::vector<std::string> passes_commands;
std::string output_filename = "-";
std::string scriptfile = "";
bool got_output_filename = false;
RTLIL::Design *design = new RTLIL::Design;
design->selection_stack.push_back(RTLIL::Selection());
log_push();
int opt;
while ((opt = getopt(argc, argv, "f:b:o:p:l:qts:")) != -1)
{
switch (opt)
{
case 'f':
frontend_command = optarg;
break;
case 'b':
backend_command = optarg;
break;
case 'p':
passes_commands.push_back(optarg);
break;
case 'o':
output_filename = optarg;
got_output_filename = true;
break;
case 'l':
log_files.push_back(fopen(optarg, "wt"));
if (log_files.back() == NULL) {
fprintf(stderr, "Can't open log file `%s' for writing!\n", optarg);
exit(1);
}
break;
case 'q':
log_errfile = stderr;
break;
case 't':
log_time = true;
break;
case 's':
scriptfile = optarg;
break;
default:
fprintf(stderr, "Usage: %s [-q] [-t] [-l logfile] [-o <outfile>] [-f <frontend>] [-s <scriptfile>] [-p <pass> [-p ..]] [-b <backend>] [<infile> [..]]\n", argv[0]);
exit(1);
}
}
if (log_errfile == NULL)
log_files.push_back(stderr);
if (optind == argc && passes_commands.size() == 0 && scriptfile.empty())
{
log_cmd_error_throw = true;
rl_readline_name = "yosys";
rl_attempted_completion_function = readline_completion;
char *command = NULL;
while ((command = readline(create_prompt(design))) != NULL)
{
if (command[strspn(command, " \t\r\n")] == 0)
continue;
add_history(command);
try {
assert(design->selection_stack.size() == 1);
Pass::call(design, command);
} catch (int) {
while (design->selection_stack.size() > 1)
design->selection_stack.pop_back();
log_reset_stack();
}
}
if (!got_output_filename)
backend_command = "";
log_cmd_error_throw = false;
}
while (optind < argc)
run_frontend(argv[optind++], frontend_command, design, output_filename == "-" ? &backend_command : NULL);
if (!scriptfile.empty())
run_frontend(scriptfile, "script", design, output_filename == "-" ? &backend_command : NULL);
for (auto it = passes_commands.begin(); it != passes_commands.end(); it++)
run_pass(*it, design);
if (!backend_command.empty())
run_backend(output_filename, backend_command, design);
delete design;
log("\nREADY.\n");
log_pop();
for (auto f : log_files)
if (f != stderr)
fclose(f);
log_errfile = NULL;
log_files.clear();
return 0;
}

197
kernel/log.cc Normal file
View file

@ -0,0 +1,197 @@
/*
* 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/log.h"
#include "backends/ilang/ilang_backend.h"
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <vector>
#include <list>
std::vector<FILE*> log_files;
FILE *log_errfile = NULL;
bool log_time = false;
bool log_cmd_error_throw = false;
std::vector<int> header_count;
std::list<std::string> string_buf;
static struct timeval initial_tv = { 0, 0 };
static bool next_print_log = false;
std::string stringf(const char *fmt, ...)
{
std::string string;
char *str = NULL;
va_list ap;
va_start(ap, fmt);
if (vasprintf(&str, fmt, ap) < 0)
str = NULL;
va_end(ap);
if (str != NULL) {
string = str;
free(str);
}
return string;
}
void logv(const char *format, va_list ap)
{
if (log_time) {
while (format[0] == '\n' && format[1] != 0) {
format++;
log("\n");
}
if (next_print_log || initial_tv.tv_sec == 0) {
next_print_log = false;
struct timeval tv;
gettimeofday(&tv, NULL);
if (initial_tv.tv_sec == 0)
initial_tv = tv;
if (tv.tv_usec < initial_tv.tv_usec) {
tv.tv_sec--;
tv.tv_usec += 1000000;
}
tv.tv_sec -= initial_tv.tv_sec;
tv.tv_usec -= initial_tv.tv_usec;
log("[%05d.%06d] ", int(tv.tv_sec), int(tv.tv_usec));
}
if (format[0] && format[strlen(format)-1] == '\n')
next_print_log = true;
}
for (auto f : log_files) {
va_list aq;
va_copy(aq, ap);
vfprintf(f, format, aq);
va_end(aq);
}
}
void logv_header(const char *format, va_list ap)
{
log("\n");
if (header_count.size() > 0)
header_count.back()++;
for (int c : header_count)
log("%d.", c);
log(" ");
logv(format, ap);
log_flush();
}
void logv_error(const char *format, va_list ap)
{
log("ERROR: ");
logv(format, ap);
if (log_errfile != NULL) {
fprintf(log_errfile, "ERROR: ");
vfprintf(log_errfile, format, ap);
}
log_flush();
exit(1);
}
void log(const char *format, ...)
{
va_list ap;
va_start(ap, format);
logv(format, ap);
va_end(ap);
}
void log_header(const char *format, ...)
{
va_list ap;
va_start(ap, format);
logv_header(format, ap);
va_end(ap);
}
void log_error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
logv_error(format, ap);
}
void log_cmd_error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
if (log_cmd_error_throw) {
log("ERROR: ");
logv(format, ap);
log_flush();
throw 0;
}
logv_error(format, ap);
}
void log_push()
{
header_count.push_back(0);
}
void log_pop()
{
header_count.pop_back();
string_buf.clear();
log_flush();
}
void log_reset_stack()
{
while (header_count.size() > 1)
header_count.pop_back();
string_buf.clear();
log_flush();
}
void log_flush()
{
for (auto f : log_files)
fflush(f);
}
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint)
{
char *ptr;
size_t size;
FILE *f = open_memstream(&ptr, &size);
ILANG_BACKEND::dump_sigspec(f, sig, autoint);
fputc(0, f);
fclose(f);
string_buf.push_back(ptr);
free(ptr);
return string_buf.back().c_str();
}

51
kernel/log.h Normal file
View file

@ -0,0 +1,51 @@
/*
* 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 LOG_H
#define LOG_H
#include "kernel/rtlil.h"
#include <stdio.h>
#include <vector>
extern std::vector<FILE*> log_files;
extern FILE *log_errfile;
extern bool log_time;
extern bool log_cmd_error_throw;
std::string stringf(const char *fmt, ...);
void logv(const char *format, va_list ap);
void logv_header(const char *format, va_list ap);
void logv_error(const char *format, va_list ap) __attribute__ ((noreturn));
void log(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void log_header(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void log_error(const char *format, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((noreturn));
void log_cmd_error(const char *format, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((noreturn));
void log_push();
void log_pop();
void log_reset_stack();
void log_flush();
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
#endif

288
kernel/register.cc Normal file
View file

@ -0,0 +1,288 @@
/*
* 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 "register.h"
#include "log.h"
#include <assert.h>
#include <string.h>
using namespace REGISTER_INTERN;
namespace REGISTER_INTERN {
std::map<std::string, Frontend*> frontend_register;
std::map<std::string, Pass*> pass_register;
std::map<std::string, Backend*> backend_register;
}
std::vector<std::string> Frontend::next_args;
Pass::Pass(std::string name) : pass_name(name)
{
assert(pass_register.count(name) == 0);
pass_register[name] = this;
}
Pass::~Pass()
{
pass_register.erase(pass_name);
}
void Pass::help()
{
log("No help message for this command.\n");
}
void Pass::cmd_log_args(const std::vector<std::string> &args)
{
if (args.size() <= 1)
return;
log("Full command line:");
for (size_t i = 0; i < args.size(); i++)
log(" %s", args[i].c_str());
log("\n");
}
void Pass::cmd_error(const std::vector<std::string> &args, size_t argidx, std::string msg)
{
std::string command_text;
int error_pos = 0;
for (size_t i = 0; i < args.size(); i++) {
if (i < argidx)
error_pos += args[i].size() + 1;
command_text = command_text + (command_text.empty() ? "" : " ") + args[i];
}
log("\nSyntax error in command `%s':\n", command_text.c_str());
help();
log_cmd_error("Command syntax error: %s\n> %s\n> %*s^\n",
msg.c_str(), command_text.c_str(), error_pos, "");
}
void Pass::extra_args(std::vector<std::string> args, size_t argidx, RTLIL::Design *)
{
for (; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
if (arg.substr(0, 1) == "-")
cmd_error(args, argidx, "Unkown option or option in arguments.");
cmd_error(args, argidx, "Extra argument.");
}
cmd_log_args(args);
}
void Pass::call(RTLIL::Design *design, std::string command)
{
std::vector<std::string> args;
char *s = strdup(command.c_str());
for (char *p = strtok(s, " \t\r\n"); p; p = strtok(NULL, " \t\r\n"))
args.push_back(p);
free(s);
call(design, args);
}
void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
{
if (args.size() == 0 || args[0][0] == '#')
return;
if (pass_register.count(args[0]) == 0)
log_cmd_error("No such command: %s\n", args[0].c_str());
size_t orig_sel_stack_pos = design->selection_stack.size();
pass_register[args[0]]->execute(args, design);
while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back();
}
Frontend::Frontend(std::string name) : Pass("read_"+name), frontend_name(name)
{
assert(frontend_register.count(name) == 0);
frontend_register[name] = this;
}
Frontend::~Frontend()
{
frontend_register.erase(frontend_name);
}
void Frontend::execute(std::vector<std::string> args, RTLIL::Design *design)
{
assert(next_args.empty());
do {
FILE *f = NULL;
next_args.clear();
execute(f, std::string(), args, design);
args = next_args;
fclose(f);
} while (!args.empty());
}
void Frontend::extra_args(FILE *&f, std::string &filename, std::vector<std::string> args, size_t argidx)
{
bool called_with_fp = f != NULL;
next_args.clear();
for (; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
if (arg.substr(0, 1) == "-")
cmd_error(args, argidx, "Unkown option or option in arguments.");
if (f != NULL)
cmd_error(args, argidx, "Extra filename argument in direct file mode.");
filename = arg;
f = fopen(filename.c_str(), "r");
if (f == NULL)
log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
if (argidx+1 < args.size()) {
next_args.insert(next_args.begin(), args.begin(), args.begin()+argidx);
next_args.insert(next_args.begin()+argidx, args.begin()+argidx+1, args.end());
args.erase(args.begin()+argidx+1, args.end());
}
break;
}
if (f == NULL)
cmd_error(args, argidx, "No filename given.");
if (called_with_fp)
args.push_back(filename);
args[0] = pass_name;
cmd_log_args(args);
}
void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::string command)
{
std::vector<std::string> args;
char *s = strdup(command.c_str());
for (char *p = strtok(s, " \t\r\n"); p; p = strtok(NULL, " \t\r\n"))
args.push_back(p);
free(s);
frontend_call(design, f, filename, args);
}
void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::vector<std::string> args)
{
if (args.size() == 0)
return;
if (frontend_register.count(args[0]) == 0)
log_cmd_error("No such frontend: %s\n", args[0].c_str());
if (f != NULL) {
frontend_register[args[0]]->execute(f, filename, args, design);
} else if (filename == "-") {
frontend_register[args[0]]->execute(stdin, "<stdin>", args, design);
} else {
if (!filename.empty())
args.push_back(filename);
frontend_register[args[0]]->execute(args, design);
}
}
Backend::Backend(std::string name) : Pass("write_"+name), backend_name(name)
{
assert(backend_register.count(name) == 0);
backend_register[name] = this;
}
Backend::~Backend()
{
backend_register.erase(backend_name);
}
void Backend::execute(std::vector<std::string> args, RTLIL::Design *design)
{
FILE *f = NULL;
execute(f, std::string(), args, design);
if (f != stdout)
fclose(f);
}
void Backend::extra_args(FILE *&f, std::string &filename, std::vector<std::string> args, size_t argidx)
{
bool called_with_fp = f != NULL;
for (; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
if (arg.substr(0, 1) == "-" && arg != "-")
cmd_error(args, argidx, "Unkown option or option in arguments.");
if (f != NULL)
cmd_error(args, argidx, "Extra filename argument in direct file mode.");
if (arg == "-") {
filename = "<stdout>";
f = stdout;
continue;
}
filename = arg;
f = fopen(filename.c_str(), "w");
if (f == NULL)
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
}
if (called_with_fp)
args.push_back(filename);
args[0] = pass_name;
cmd_log_args(args);
if (f == NULL) {
filename = "<stdout>";
f = stdout;
}
}
void Backend::backend_call(RTLIL::Design *design, FILE *f, std::string filename, std::string command)
{
std::vector<std::string> args;
char *s = strdup(command.c_str());
for (char *p = strtok(s, " \t\r\n"); p; p = strtok(NULL, " \t\r\n"))
args.push_back(p);
free(s);
backend_call(design, f, filename, args);
}
void Backend::backend_call(RTLIL::Design *design, FILE *f, std::string filename, std::vector<std::string> args)
{
if (args.size() == 0)
return;
if (backend_register.count(args[0]) == 0)
log_cmd_error("No such backend: %s\n", args[0].c_str());
size_t orig_sel_stack_pos = design->selection_stack.size();
if (f != NULL) {
backend_register[args[0]]->execute(f, filename, args, design);
} else if (filename == "-") {
backend_register[args[0]]->execute(stdout, "<stdout>", args, design);
} else {
if (!filename.empty())
args.push_back(filename);
backend_register[args[0]]->execute(args, design);
}
while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back();
}

80
kernel/register.h Normal file
View file

@ -0,0 +1,80 @@
/*
* 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 REGISTER_H
#define REGISTER_H
#include "kernel/rtlil.h"
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
struct Pass
{
std::string pass_name;
Pass(std::string name);
virtual ~Pass();
virtual void help();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) = 0;
void cmd_log_args(const std::vector<std::string> &args);
void cmd_error(const std::vector<std::string> &args, size_t argidx, std::string msg);
void extra_args(std::vector<std::string> args, size_t argidx, RTLIL::Design *design);
static void call(RTLIL::Design *design, std::string command);
static void call(RTLIL::Design *design, std::vector<std::string> args);
};
struct Frontend : Pass
{
std::string frontend_name;
Frontend(std::string name);
virtual ~Frontend();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design);
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
static std::vector<std::string> next_args;
void extra_args(FILE *&f, std::string &filename, std::vector<std::string> args, size_t argidx);
static void frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::string command);
static void frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::vector<std::string> args);
};
struct Backend : Pass
{
std::string backend_name;
Backend(std::string name);
virtual ~Backend();
virtual void execute(std::vector<std::string> args, RTLIL::Design *design);
virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
void extra_args(FILE *&f, std::string &filename, std::vector<std::string> args, size_t argidx);
static void backend_call(RTLIL::Design *design, FILE *f, std::string filename, std::string command);
static void backend_call(RTLIL::Design *design, FILE *f, std::string filename, std::vector<std::string> args);
};
namespace REGISTER_INTERN {
extern std::map<std::string, Pass*> pass_register;
extern std::map<std::string, Frontend*> frontend_register;
extern std::map<std::string, Backend*> backend_register;
}
#endif

1081
kernel/rtlil.cc Normal file

File diff suppressed because it is too large Load diff

341
kernel/rtlil.h Normal file
View file

@ -0,0 +1,341 @@
/*
* 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 RTLIL_H
#define RTLIL_H
#include <map>
#include <set>
#include <vector>
#include <string>
#include <assert.h>
std::string stringf(const char *fmt, ...);
namespace RTLIL
{
enum State {
S0 = 0,
S1 = 1,
Sx = 2, // undefined value or conflict
Sz = 3, // high-impedance / not-connected
Sa = 4, // don't care (used only in cases)
Sm = 5 // marker (used internally by some passes)
};
enum SyncType {
ST0 = 0, // level sensitive: 0
ST1 = 1, // level sensitive: 1
STp = 2, // edge sensitive: posedge
STn = 3, // edge sensitive: negedge
STe = 4, // edge sensitive: both edges
STa = 5 // always active
};
extern int autoidx;
struct Const;
struct Selection;
struct Design;
struct Module;
struct Wire;
struct Memory;
struct Cell;
struct SigChunk;
struct SigSpec;
struct CaseRule;
struct SwitchRule;
struct SyncRule;
struct Process;
typedef std::pair<SigSpec, SigSpec> SigSig;
#ifdef NDEBUG
typedef std::string IdString;
#else
struct IdString : public std::string {
IdString() { }
IdString(std::string str) : std::string(str) {
check();
}
IdString(const char *s) : std::string(s) {
check();
}
IdString &operator=(const std::string &str) {
std::string::operator=(str);
check();
return *this;
}
IdString &operator=(const char *s) {
std::string::operator=(s);
check();
return *this;
}
bool operator<(const IdString &rhs) {
check(), rhs.check();
return std::string(*this) < std::string(rhs);
}
void check() const {
assert(empty() || (size() >= 2 && (at(0) == '$' || at(0) == '\\')));
}
};
#endif
static IdString escape_id(std::string str) __attribute__((unused));
static IdString escape_id(std::string str) {
if (str.size() > 0 && str[0] != '\\' && str[0] != '$')
return "\\" + str;
return str;
}
static std::string unescape_id(std::string str) __attribute__((unused));
static std::string unescape_id(std::string str) {
if (str.size() > 0 && str[0] == '\\')
return str.substr(1);
return str;
}
static IdString new_id(std::string file, int line, std::string func) __attribute__((unused));
static IdString new_id(std::string file, int line, std::string func) {
std::string str = "$auto$";
size_t pos = file.find_last_of('/');
str += pos != std::string::npos ? file.substr(pos+1) : file;
str += stringf(":%d:%s$%d", line, func.c_str(), autoidx++);
return str;
}
#define NEW_ID \
RTLIL::new_id(__FILE__, __LINE__, __FUNCTION__)
// see calc.cc for the implementation of this functions
RTLIL::Const const_not (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_and (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_or (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_xor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_xnor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_reduce_and (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_reduce_or (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_reduce_xor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_reduce_xnor (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_reduce_bool (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_logic_not (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_logic_and (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_logic_or (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_shl (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_shr (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_sshl (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_sshr (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_lt (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_le (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_eq (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_ne (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_ge (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_gt (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_add (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_sub (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_mul (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_div (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_mod (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_pow (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
};
struct RTLIL::Const {
std::string str;
std::vector<RTLIL::State> bits;
Const(std::string str = std::string());
Const(int val, int width = 32);
Const(RTLIL::State bit, int width = 1);
Const(std::vector<RTLIL::State> bits) : bits(bits) { };
bool operator <(const RTLIL::Const &other) const;
bool operator ==(const RTLIL::Const &other) const;
bool operator !=(const RTLIL::Const &other) const;
bool as_bool() const;
int as_int() const;
std::string as_string() const;
};
struct RTLIL::Selection {
bool full_selection;
std::set<RTLIL::IdString> selected_modules;
std::map<RTLIL::IdString, std::set<RTLIL::IdString>> selected_members;
Selection(bool full = true) : full_selection(full) { }
bool selected_module(RTLIL::IdString mod_name);
bool selected_whole_module(RTLIL::IdString mod_name);
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name);
void optimize(RTLIL::Design *design);
};
struct RTLIL::Design {
std::map<RTLIL::IdString, RTLIL::Module*> modules;
std::vector<RTLIL::Selection> selection_stack;
std::map<RTLIL::IdString, RTLIL::Selection> selection_vars;
std::string selected_active_module;
~Design();
void check();
void optimize();
bool selected_module(RTLIL::IdString mod_name);
bool selected_whole_module(RTLIL::IdString mod_name);
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name);
template<typename T1> bool selected(T1 *module) {
return selected_module(module->name);
}
template<typename T1, typename T2> bool selected(T1 *module, T2 *member) {
return selected_member(module->name, member->name);
}
};
struct RTLIL::Module {
RTLIL::IdString name;
std::map<RTLIL::IdString, RTLIL::Wire*> wires;
std::map<RTLIL::IdString, RTLIL::Memory*> memories;
std::map<RTLIL::IdString, RTLIL::Cell*> cells;
std::map<RTLIL::IdString, RTLIL::Process*> processes;
std::vector<RTLIL::SigSig> connections;
std::map<RTLIL::IdString, RTLIL::Const> attributes;
virtual ~Module();
virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters);
virtual void update_auto_wires(std::map<RTLIL::IdString, int> auto_sizes);
virtual size_t count_id(RTLIL::IdString id);
virtual void check();
virtual void optimize();
void add(RTLIL::Wire *wire);
void add(RTLIL::Cell *cell);
};
struct RTLIL::Wire {
RTLIL::IdString name;
int width, start_offset, port_id;
bool port_input, port_output, auto_width;
std::map<RTLIL::IdString, RTLIL::Const> attributes;
Wire();
};
struct RTLIL::Memory {
RTLIL::IdString name;
int width, start_offset, size;
std::map<RTLIL::IdString, RTLIL::Const> attributes;
Memory();
};
struct RTLIL::Cell {
RTLIL::IdString name;
RTLIL::IdString type;
std::map<RTLIL::IdString, RTLIL::SigSpec> connections;
std::map<RTLIL::IdString, RTLIL::Const> attributes;
std::map<RTLIL::IdString, RTLIL::Const> parameters;
void optimize();
};
struct RTLIL::SigChunk {
RTLIL::Wire *wire;
RTLIL::Const data; // only used if wire == NULL, LSB at index 0
int width, offset;
SigChunk();
SigChunk(const RTLIL::Const &data);
SigChunk(RTLIL::Wire *wire, int width, int offset);
SigChunk(const std::string &str);
SigChunk(int val, int width = 32);
SigChunk(RTLIL::State bit, int width = 1);
RTLIL::SigChunk extract(int offset, int length) const;
bool operator <(const RTLIL::SigChunk &other) const;
bool operator ==(const RTLIL::SigChunk &other) const;
bool operator !=(const RTLIL::SigChunk &other) const;
};
struct RTLIL::SigSpec {
std::vector<RTLIL::SigChunk> chunks; // LSB at index 0
int width;
SigSpec();
SigSpec(const RTLIL::Const &data);
SigSpec(const RTLIL::SigChunk &chunk);
SigSpec(RTLIL::Wire *wire, int width = -1, int offset = 0);
SigSpec(const std::string &str);
SigSpec(int val, int width = 32);
SigSpec(RTLIL::State bit, int width = 1);
void expand();
void optimize();
void sort_and_unify();
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with);
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with, RTLIL::SigSpec *other) const;
void remove(const RTLIL::SigSpec &pattern);
void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const;
void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other);
RTLIL::SigSpec extract(RTLIL::SigSpec pattern, RTLIL::SigSpec *other = NULL) const;
void replace(int offset, const RTLIL::SigSpec &with);
void remove_const();
void remove(int offset, int length);
RTLIL::SigSpec extract(int offset, int length) const;
void append(const RTLIL::SigSpec &signal);
bool combine(RTLIL::SigSpec signal, RTLIL::State freeState = RTLIL::State::Sz, bool override = false);
void extend(int width, bool is_signed = false);
void check() const;
bool operator <(const RTLIL::SigSpec &other) const;
bool operator ==(const RTLIL::SigSpec &other) const;
bool operator !=(const RTLIL::SigSpec &other) const;
bool is_fully_const() const;
bool is_fully_def() const;
bool is_fully_undef() const;
bool has_marked_bits() const;
bool as_bool() const;
int as_int() const;
std::string as_string() const;
RTLIL::Const as_const() const;
bool match(std::string pattern) const;
};
struct RTLIL::CaseRule {
std::vector<RTLIL::SigSpec> compare;
std::vector<RTLIL::SigSig> actions;
std::vector<RTLIL::SwitchRule*> switches;
~CaseRule();
void optimize();
};
struct RTLIL::SwitchRule {
RTLIL::SigSpec signal;
std::map<RTLIL::IdString, RTLIL::Const> attributes;
std::vector<RTLIL::CaseRule*> cases;
~SwitchRule();
void optimize();
};
struct RTLIL::SyncRule {
RTLIL::SyncType type;
RTLIL::SigSpec signal;
std::vector<RTLIL::SigSig> actions;
void optimize();
};
struct RTLIL::Process {
RTLIL::IdString name;
std::map<RTLIL::IdString, RTLIL::Const> attributes;
RTLIL::CaseRule root_case;
std::vector<RTLIL::SyncRule*> syncs;
~Process();
void optimize();
};
#endif

476
kernel/select.cc Normal file
View file

@ -0,0 +1,476 @@
/*
* 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/register.h"
#include "kernel/log.h"
#include <string.h>
#include <fnmatch.h>
static std::vector<RTLIL::Selection> work_stack;
static bool match_ids(RTLIL::IdString id, std::string pattern)
{
if (!fnmatch(pattern.c_str(), id.c_str(), FNM_NOESCAPE))
return true;
if (id.size() > 0 && id[0] == '\\' && !fnmatch(pattern.c_str(), id.substr(1).c_str(), FNM_NOESCAPE))
return true;
return false;
}
static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
{
if (lhs.full_selection) {
lhs.full_selection = false;
lhs.selected_modules.clear();
lhs.selected_members.clear();
return;
}
if (lhs.selected_modules.size() == 0 && lhs.selected_members.size() == 0) {
lhs.full_selection = true;
return;
}
RTLIL::Selection new_sel(false);
for (auto &mod_it : design->modules)
{
if (lhs.selected_whole_module(mod_it.first))
continue;
if (!lhs.selected_module(mod_it.first)) {
new_sel.selected_modules.insert(mod_it.first);
continue;
}
RTLIL::Module *mod = mod_it.second;
for (auto &it : mod->wires)
if (!lhs.selected_member(mod_it.first, it.first))
new_sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->memories)
if (!lhs.selected_member(mod_it.first, it.first))
new_sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->cells)
if (!lhs.selected_member(mod_it.first, it.first))
new_sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->processes)
if (!lhs.selected_member(mod_it.first, it.first))
new_sel.selected_members[mod->name].insert(it.first);
}
lhs.selected_modules.swap(new_sel.selected_modules);
lhs.selected_members.swap(new_sel.selected_members);
}
static void select_op_union(RTLIL::Design*, RTLIL::Selection &lhs, const RTLIL::Selection &rhs)
{
if (rhs.full_selection) {
lhs.full_selection = true;
lhs.selected_modules.clear();
lhs.selected_members.clear();
return;
}
if (lhs.full_selection)
return;
for (auto &it : rhs.selected_members)
for (auto &it2 : it.second)
lhs.selected_members[it.first].insert(it2);
for (auto &it : rhs.selected_modules) {
lhs.selected_modules.insert(it);
lhs.selected_members.erase(it);
}
}
static void select_op_diff(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs)
{
if (rhs.full_selection) {
lhs.full_selection = false;
lhs.selected_modules.clear();
lhs.selected_members.clear();
return;
}
if (lhs.full_selection) {
if (!rhs.full_selection && rhs.selected_modules.size() == 0 && rhs.selected_members.size() == 0)
return;
lhs.full_selection = false;
for (auto &it : design->modules)
lhs.selected_modules.insert(it.first);
}
for (auto &it : rhs.selected_modules) {
lhs.selected_modules.erase(it);
lhs.selected_members.erase(it);
}
for (auto &it : rhs.selected_members)
{
if (design->modules.count(it.first) == 0)
continue;
RTLIL::Module *mod = design->modules[it.first];
if (lhs.selected_modules.count(mod->name) > 0)
{
for (auto &it : mod->wires)
lhs.selected_members[mod->name].insert(it.first);
for (auto &it : mod->memories)
lhs.selected_members[mod->name].insert(it.first);
for (auto &it : mod->cells)
lhs.selected_members[mod->name].insert(it.first);
for (auto &it : mod->processes)
lhs.selected_members[mod->name].insert(it.first);
lhs.selected_modules.erase(mod->name);
}
if (lhs.selected_members.count(mod->name) == 0)
continue;
for (auto &it2 : it.second)
lhs.selected_members[mod->name].erase(it2);
}
}
static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, const RTLIL::Selection &rhs)
{
if (rhs.full_selection)
return;
if (lhs.full_selection) {
lhs.full_selection = false;
for (auto &it : design->modules)
lhs.selected_modules.insert(it.first);
}
std::vector<RTLIL::IdString> del_list;
for (auto &it : lhs.selected_modules)
if (rhs.selected_modules.count(it) == 0) {
if (rhs.selected_members.count(it) > 0)
for (auto &it2 : rhs.selected_members.at(it))
lhs.selected_members[it].insert(it2);
del_list.push_back(it);
}
for (auto &it : del_list)
lhs.selected_modules.erase(it);
del_list.clear();
for (auto &it : lhs.selected_members) {
if (rhs.selected_modules.count(it.first) > 0)
continue;
if (rhs.selected_members.count(it.first) == 0) {
del_list.push_back(it.first);
continue;
}
std::vector<RTLIL::IdString> del_list2;
for (auto &it2 : it.second)
if (rhs.selected_members.at(it.first).count(it2) == 0)
del_list2.push_back(it2);
for (auto &it2 : del_list2)
it.second.erase(it2);
if (it.second.size() == 0)
del_list.push_back(it.first);
}
for (auto &it : del_list)
lhs.selected_members.erase(it);
}
static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &sel)
{
if (design->selected_active_module.empty())
return;
if (sel.full_selection) {
sel.full_selection = false;
sel.selected_modules.clear();
sel.selected_members.clear();
sel.selected_modules.insert(design->selected_active_module);
return;
}
std::vector<std::string> del_list;
for (auto mod_name : sel.selected_modules)
if (mod_name != design->selected_active_module)
del_list.push_back(mod_name);
for (auto &it : sel.selected_members)
if (it.first != design->selected_active_module)
del_list.push_back(it.first);
for (auto mod_name : del_list) {
sel.selected_modules.erase(mod_name);
sel.selected_members.erase(mod_name);
}
}
static void select_stmt(RTLIL::Design *design, std::string arg)
{
std::string arg_mod, arg_memb;
if (arg.size() == 0)
return;
if (arg[0] == '#') {
if (arg == "#") {
if (design->selection_stack.size() > 0)
work_stack.push_back(design->selection_stack.back());
} else
if (arg == "#n") {
if (work_stack.size() < 1)
log_cmd_error("Must have at least one element on stack for operator #n.\n");
select_op_neg(design, work_stack[work_stack.size()-1]);
} else
if (arg == "#u") {
if (work_stack.size() < 2)
log_cmd_error("Must have at least two elements on stack for operator #u.\n");
select_op_union(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
work_stack.pop_back();
} else
if (arg == "#d") {
if (work_stack.size() < 2)
log_cmd_error("Must have at least two elements on stack for operator #d.\n");
select_op_diff(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
work_stack.pop_back();
} else
if (arg == "#i") {
if (work_stack.size() < 2)
log_cmd_error("Must have at least two elements on stack for operator #i.\n");
select_op_intersect(design, work_stack[work_stack.size()-2], work_stack[work_stack.size()-1]);
work_stack.pop_back();
} else
log_cmd_error("Unknown selection operator '%s'.\n", arg.c_str());
select_filter_active_mod(design, work_stack.back());
return;
}
if (!design->selected_active_module.empty()) {
arg_mod = design->selected_active_module;
arg_memb = arg;
} else {
size_t pos = arg.find('/');
if (pos == std::string::npos) {
arg_mod = arg;
} else {
arg_mod = arg.substr(0, pos);
arg_memb = arg.substr(pos+1);
}
}
work_stack.push_back(RTLIL::Selection());
RTLIL::Selection &sel = work_stack.back();
if (arg == "*" && arg_mod == "*") {
select_filter_active_mod(design, work_stack.back());
return;
}
sel.full_selection = false;
for (auto &mod_it : design->modules)
{
if (!match_ids(mod_it.first, arg_mod))
continue;
if (arg_memb == "") {
sel.selected_modules.insert(mod_it.first);
continue;
}
RTLIL::Module *mod = mod_it.second;
if (arg_memb.substr(0, 2) == "w:") {
for (auto &it : mod->wires)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "m:") {
for (auto &it : mod->memories)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "c:") {
for (auto &it : mod->cells)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "t:") {
for (auto &it : mod->cells)
if (match_ids(it.second->type, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else
if (arg_memb.substr(0, 2) == "p:") {
for (auto &it : mod->processes)
if (match_ids(it.first, arg_memb.substr(2)))
sel.selected_members[mod->name].insert(it.first);
} else {
if (arg_memb.substr(0, 2) == "n:")
arg_memb = arg_memb.substr(2);
for (auto &it : mod->wires)
if (match_ids(it.first, arg_memb))
sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->memories)
if (match_ids(it.first, arg_memb))
sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->cells)
if (match_ids(it.first, arg_memb))
sel.selected_members[mod->name].insert(it.first);
for (auto &it : mod->processes)
if (match_ids(it.first, arg_memb))
sel.selected_members[mod->name].insert(it.first);
}
}
select_filter_active_mod(design, work_stack.back());
}
struct SelectPass : public Pass {
SelectPass() : Pass("select") { }
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
bool add_mode = false;
bool del_mode = false;
bool clear_mode = false;
bool list_mode = false;
bool got_module = false;
work_stack.clear();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
if (arg == "-add") {
add_mode = true;
continue;
}
if (arg == "-del") {
del_mode = true;
continue;
}
if (arg == "-clear") {
clear_mode = true;
continue;
}
if (arg == "-list") {
list_mode = true;
continue;
}
if (arg == "-module" && argidx+1 < args.size()) {
RTLIL::IdString mod_name = RTLIL::escape_id(args[++argidx]);
if (design->modules.count(mod_name) == 0)
log_cmd_error("No such module: %s\n", mod_name.c_str());
design->selected_active_module = mod_name;
got_module = true;
continue;
}
if (arg.size() > 0 && arg[0] == '-')
log_cmd_error("Unkown option %s.\n", arg.c_str());
select_stmt(design, arg);
}
if (clear_mode && args.size() != 2)
log_cmd_error("Option -clear can not be combined with other options.\n");
if (add_mode && del_mode)
log_cmd_error("Options -add and -del can not be combined.\n");
if (list_mode && (add_mode || del_mode))
log_cmd_error("Option -list can not be combined with -add or -del.\n");
if (work_stack.size() == 0 && got_module) {
RTLIL::Selection sel;
select_filter_active_mod(design, sel);
work_stack.push_back(sel);
}
while (work_stack.size() > 1) {
select_op_union(design, work_stack.front(), work_stack.back());
work_stack.pop_back();
}
assert(design->selection_stack.size() > 0);
if (clear_mode)
{
design->selection_stack.back() = RTLIL::Selection(true);
design->selected_active_module = std::string();
return;
}
if (list_mode)
{
RTLIL::Selection *sel = &design->selection_stack.back();
if (work_stack.size() > 0)
sel = &work_stack.back();
sel->optimize(design);
for (auto mod_it : design->modules)
{
if (design->selected_whole_module(mod_it.first))
log("%s\n", mod_it.first.c_str());
if (design->selected_module(mod_it.first)) {
for (auto &it : mod_it.second->wires)
if (design->selected_member(mod_it.first, it.first))
log("%s/%s\n", mod_it.first.c_str(), it.first.c_str());
for (auto &it : mod_it.second->memories)
if (design->selected_member(mod_it.first, it.first))
log("%s/%s\n", mod_it.first.c_str(), it.first.c_str());
for (auto &it : mod_it.second->cells)
if (design->selected_member(mod_it.first, it.first))
log("%s/%s\n", mod_it.first.c_str(), it.first.c_str());
for (auto &it : mod_it.second->processes)
if (design->selected_member(mod_it.first, it.first))
log("%s/%s\n", mod_it.first.c_str(), it.first.c_str());
}
}
return;
}
if (add_mode)
{
if (work_stack.size() == 0)
log_cmd_error("Nothing to add to selection.\n");
select_op_union(design, design->selection_stack.back(), work_stack.back());
design->selection_stack.back().optimize(design);
return;
}
if (del_mode)
{
if (work_stack.size() == 0)
log_cmd_error("Nothing to delete from selection.\n");
select_op_diff(design, design->selection_stack.back(), work_stack.back());
design->selection_stack.back().optimize(design);
return;
}
if (work_stack.size() == 0) {
RTLIL::Selection &sel = design->selection_stack.back();
if (sel.full_selection)
log("*\n");
for (auto &it : sel.selected_modules)
log("%s\n", it.c_str());
for (auto &it : sel.selected_members)
for (auto &it2 : it.second)
log("%s/%s\n", it.first.c_str(), it2.c_str());
return;
}
design->selection_stack.back() = work_stack.back();
design->selection_stack.back().optimize(design);
}
} SelectPass;

185
kernel/sha1.cpp Normal file
View file

@ -0,0 +1,185 @@
/*
Copyright (c) 2011, Micael Hildenborg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Micael Hildenborg nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Contributors:
Gustav
Several members in the gamedev.se forum.
Gregory Petrosyan
*/
#include "sha1.h"
namespace sha1
{
namespace // local
{
// Rotate an integer value to left.
inline unsigned int rol(const unsigned int value,
const unsigned int steps)
{
return ((value << steps) | (value >> (32 - steps)));
}
// Sets the first 16 integers in the buffert to zero.
// Used for clearing the W buffert.
inline void clearWBuffert(unsigned int* buffert)
{
for (int pos = 16; --pos >= 0;)
{
buffert[pos] = 0;
}
}
void innerHash(unsigned int* result, unsigned int* w)
{
unsigned int a = result[0];
unsigned int b = result[1];
unsigned int c = result[2];
unsigned int d = result[3];
unsigned int e = result[4];
int round = 0;
#define sha1macro(func,val) \
{ \
const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
e = d; \
d = c; \
c = rol(b, 30); \
b = a; \
a = t; \
}
while (round < 16)
{
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 20)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 40)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0x6ed9eba1)
++round;
}
while (round < 60)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
++round;
}
while (round < 80)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0xca62c1d6)
++round;
}
#undef sha1macro
result[0] += a;
result[1] += b;
result[2] += c;
result[3] += d;
result[4] += e;
}
} // namespace
void calc(const void* src, const int bytelength, unsigned char* hash)
{
// Init the result array.
unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
// Cast the void src pointer to be the byte array we can work with.
const unsigned char* sarray = (const unsigned char*) src;
// The reusable round buffer
unsigned int w[80];
// Loop through all complete 64byte blocks.
const int endOfFullBlocks = bytelength - 64;
int endCurrentBlock;
int currentBlock = 0;
while (currentBlock <= endOfFullBlocks)
{
endCurrentBlock = currentBlock + 64;
// Init the round buffer with the 64 byte block data.
for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
{
// This line will swap endian on big endian and keep endian on little endian.
w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
| (((unsigned int) sarray[currentBlock + 2]) << 8)
| (((unsigned int) sarray[currentBlock + 1]) << 16)
| (((unsigned int) sarray[currentBlock]) << 24);
}
innerHash(result, w);
}
// Handle the last and not full 64 byte block if existing.
endCurrentBlock = bytelength - currentBlock;
clearWBuffert(w);
int lastBlockBytes = 0;
for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
{
w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
}
w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
if (endCurrentBlock >= 56)
{
innerHash(result, w);
clearWBuffert(w);
}
w[15] = bytelength << 3;
innerHash(result, w);
// Store hash in result pointer, and make sure we get in in the correct order on both endian models.
for (int hashByte = 20; --hashByte >= 0;)
{
hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
}
}
void toHexString(const unsigned char* hash, char* hexstring)
{
const char hexDigits[] = { "0123456789abcdef" };
for (int hashByte = 20; --hashByte >= 0;)
{
hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf];
hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf];
}
hexstring[40] = 0;
}
} // namespace sha1

49
kernel/sha1.h Normal file
View file

@ -0,0 +1,49 @@
/*
Copyright (c) 2011, Micael Hildenborg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Micael Hildenborg nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHA1_DEFINED
#define SHA1_DEFINED
namespace sha1
{
/**
@param src points to any kind of data to be hashed.
@param bytelength the number of bytes to hash from the src pointer.
@param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in.
*/
void calc(const void* src, const int bytelength, unsigned char* hash);
/**
@param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function.
@param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string.
*/
void toHexString(const unsigned char* hash, char* hexstring);
} // namespace sha1
#endif // SHA1_DEFINED

343
kernel/show.cc Normal file
View file

@ -0,0 +1,343 @@
/*
* 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/register.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string.h>
#include <dirent.h>
#undef CLUSTER_CELLS_AND_PORTBOXES
struct ShowWorker
{
CellTypes ct;
std::vector<std::string> dot_escape_store;
std::map<RTLIL::IdString, int> dot_id2num_store;
std::map<RTLIL::IdString, int> autonames;
int single_idx_count;
struct net_conn { std::set<std::string> in, out; };
std::map<std::string, net_conn> net_conn_map;
FILE *f;
RTLIL::Design *design;
RTLIL::Module *module;
int page_counter;
const char *escape(std::string id, bool is_name = false)
{
if (id.size() == 0)
return "";
if (id[0] == '$' && is_name) {
if (autonames.count(id) == 0) {
autonames[id] = autonames.size() + 1;
log("Generated short name for internal identifier: _%d_ -> %s\n", autonames[id], id.c_str());
}
id = stringf("_%d_", autonames[id]);
}
if (id[0] == '\\')
id = id.substr(1);
std::string str;
for (char ch : id) {
if (ch == '\\' || ch == '"')
str += "\\";
str += ch;
}
dot_escape_store.push_back(str);
return dot_escape_store.back().c_str();
}
int id2num(RTLIL::IdString id)
{
if (dot_id2num_store.count(id) > 0)
return dot_id2num_store[id];
return dot_id2num_store[id] = dot_id2num_store.size() + 1;
}
std::string gen_signode_simple(RTLIL::SigSpec sig, bool range_check = true)
{
sig.optimize();
if (sig.chunks.size() == 0) {
fprintf(f, "v%d [ label=\"\" ];\n", single_idx_count);
return stringf("v%d", single_idx_count++);
}
if (sig.chunks.size() == 1) {
RTLIL::SigChunk &c = sig.chunks[0];
if (c.wire != NULL && design->selected_member(module->name, c.wire->name)) {
if (!range_check || c.wire->width == c.width)
return stringf("n%d", id2num(c.wire->name));
} else {
fprintf(f, "v%d [ label=\"%s\" ];\n", single_idx_count, escape(log_signal(c), true));
return stringf("v%d", single_idx_count++);
}
}
return std::string();
}
std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node = NULL)
{
std::string code;
std::string net = gen_signode_simple(sig);
if (net.empty())
{
std::string label_string;
sig.optimize();
int pos = sig.width-1;
int idx = single_idx_count++;
for (int i = int(sig.chunks.size())-1; i >= 0; i--) {
RTLIL::SigChunk &c = sig.chunks[i];
net = gen_signode_simple(c, false);
assert(!net.empty());
if (driver) {
label_string += stringf("<s%d> %d:%d - %d:%d |", i, pos, pos-c.width+1, c.offset+c.width-1, c.offset);
net_conn_map[net].in.insert(stringf("x%d:s%d", idx, i));
} else {
label_string += stringf("<s%d> %d:%d - %d:%d |", i, c.offset+c.width-1, c.offset, pos, pos-c.width+1);
net_conn_map[net].out.insert(stringf("x%d:s%d", idx, i));
}
pos -= c.width;
}
if (label_string[label_string.size()-1] == '|')
label_string = label_string.substr(0, label_string.size()-1);
code += stringf("x%d [ shape=record, style=rounded, label=\"%s\" ];\n", idx, label_string.c_str());
if (!port.empty()) {
if (driver)
code += stringf("%s:e -> x%d:w [arrowhead=odiamond, arrowtail=odiamond, dir=both];\n", port.c_str(), idx);
else
code += stringf("x%d:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both];\n", idx, port.c_str());
}
if (node != NULL)
*node = stringf("x%d", idx);
}
else
{
if (!port.empty()) {
if (driver)
net_conn_map[net].in.insert(port);
else
net_conn_map[net].out.insert(port);
}
if (node != NULL)
*node = net;
}
return code;
}
void handle_module()
{
single_idx_count = 0;
dot_escape_store.clear();
dot_id2num_store.clear();
net_conn_map.clear();
fprintf(f, "digraph \"%s\" {\n", escape(module->name));
fprintf(f, "rankdir=\"LR\";\n");
fprintf(f, "remincross=true;\n");
std::map<std::string, std::string> wires_on_demand;
for (auto &it : module->wires) {
if (!design->selected_member(module->name, it.first))
continue;
const char *shape = "diamond";
if (it.second->port_input || it.second->port_output)
shape = "octagon";
if (it.first[0] == '\\')
fprintf(f, "n%d [ shape=%s, label=\"%s\" ];\n",
id2num(it.first), shape, escape(it.first));
else {
wires_on_demand[stringf("n%d", id2num(it.first))] = it.first;
}
}
for (auto &it : module->cells)
{
if (!design->selected_member(module->name, it.first))
continue;
std::vector<RTLIL::IdString> in_ports, out_ports;
for (auto &conn : it.second->connections) {
if (ct.cell_input(it.second->type, conn.first))
in_ports.push_back(conn.first);
else
out_ports.push_back(conn.first);
}
std::string label_string = "{{";
for (auto &p : in_ports)
label_string += stringf("<p%d> %s|", id2num(p), escape(p));
if (label_string[label_string.size()-1] == '|')
label_string = label_string.substr(0, label_string.size()-1);
label_string += stringf("}|%s\\n%s|{", escape(it.first, true), escape(it.second->type));
for (auto &p : out_ports)
label_string += stringf("<p%d> %s|", id2num(p), escape(p));
if (label_string[label_string.size()-1] == '|')
label_string = label_string.substr(0, label_string.size()-1);
label_string += "}}";
std::string code;
for (auto &conn : it.second->connections) {
code += gen_portbox(stringf("c%d:p%d", id2num(it.first), id2num(conn.first)),
conn.second, !ct.cell_input(it.second->type, conn.first));
}
#ifdef CLUSTER_CELLS_AND_PORTBOXES
if (!code.empty())
fprintf(f, "subgraph cluster_c%d {\nc%d [ shape=record, label=\"%s\" ];\n%s}\n",
id2num(it.first), id2num(it.first), label_string.c_str(), code.c_str());
else
#endif
fprintf(f, "c%d [ shape=record, label=\"%s\" ];\n%s",
id2num(it.first), label_string.c_str(), code.c_str());
}
for (auto &conn : module->connections)
{
bool found_lhs_wire = false;
for (auto &c : conn.first.chunks) {
if (c.wire != NULL && design->selected_member(module->name, c.wire->name))
found_lhs_wire = true;
}
bool found_rhs_wire = false;
for (auto &c : conn.second.chunks) {
if (c.wire != NULL && design->selected_member(module->name, c.wire->name))
found_rhs_wire = true;
}
if (!found_lhs_wire || !found_rhs_wire)
continue;
std::string code, left_node, right_node;
code += gen_portbox("", conn.second, false, &left_node);
code += gen_portbox("", conn.first, true, &right_node);
fprintf(f, "%s", code.c_str());
if (left_node[0] == 'x' && right_node[0] == 'x')
fprintf(f, "%s:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both];\n", left_node.c_str(), right_node.c_str());
else if (left_node[0] == 'x')
net_conn_map[right_node].in.insert(left_node);
else if (right_node[0] == 'x')
net_conn_map[left_node].out.insert(right_node);
else {
net_conn_map[right_node].in.insert(stringf("x%d:e", single_idx_count));
net_conn_map[left_node].out.insert(stringf("x%d:w", single_idx_count));
fprintf(f, "x%d [shape=box, style=rounded, label=\"BUF\"];\n", single_idx_count++);
}
}
for (auto &it : net_conn_map)
{
if (wires_on_demand.count(it.first) > 0) {
if (it.second.in.size() == 1 && it.second.out.size() == 1) {
fprintf(f, "%s:e -> %s:w;\n", it.second.in.begin()->c_str(), it.second.out.begin()->c_str());
continue;
}
if (it.second.in.size() == 0 || it.second.out.size() == 0)
fprintf(f, "%s [ shape=diamond, label=\"%s\" ];\n", it.first.c_str(), escape(wires_on_demand[it.first], true));
else
fprintf(f, "%s [ shape=point ];\n", it.first.c_str());
}
for (auto &it2 : it.second.in)
fprintf(f, "%s:e -> %s:w;\n", it2.c_str(), it.first.c_str());
for (auto &it2 : it.second.out)
fprintf(f, "%s:e -> %s:w;\n", it.first.c_str(), it2.c_str());
}
fprintf(f, "};\n");
}
ShowWorker(FILE *f, RTLIL::Design *design) : f(f), design(design)
{
ct.setup_internals();
ct.setup_internals_mem();
ct.setup_stdcells();
ct.setup_stdcells_mem();
design->optimize();
page_counter = 0;
for (auto &mod_it : design->modules)
{
module = mod_it.second;
if (!design->selected_module(module->name))
continue;
if (design->selected_whole_module(module->name))
log("Dumping module %s to page %d.\n", module->name.c_str(), ++page_counter);
else
log("Dumping selected parts of module %s to page %d.\n", module->name.c_str(), ++page_counter);
handle_module();
}
}
};
struct ShowPass : public Pass {
ShowPass() : Pass("show") { }
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
log_header("Generating Graphviz representation of design.\n");
std::string viewer_exe;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
if (arg == "-viewer" && argidx+1 < args.size()) {
viewer_exe = args[++argidx];
continue;
}
break;
}
extra_args(args, argidx, design);
log("Writing dot description to `yosys-show.dot'.\n");
FILE *f = fopen("yosys-show.dot", "w");
if (f == NULL)
log_cmd_error("Can't open dot file `yosys-show.dot' for writing.\n");
ShowWorker worker(f, design);
fclose(f);
if (worker.page_counter == 0)
log_cmd_error("Nothing there to show.\n");
std::string cmd = stringf("dot -Tps -o yosys-show.ps yosys-show.dot");
log("Exec: %s\n", cmd.c_str());
if (system(cmd.c_str()) != 0)
log_cmd_error("Shell command failed!\n");
if (!viewer_exe.empty()) {
cmd = stringf("%s yosys-show.ps &", viewer_exe.c_str());
log("Exec: %s\n", cmd.c_str());
if (system(cmd.c_str()) != 0)
log_cmd_error("Shell command failed!\n");
}
}
} ShowPass;

415
kernel/sigtools.h Normal file
View file

@ -0,0 +1,415 @@
/*
* 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 SIGTOOLS_H
#define SIGTOOLS_H
#include "kernel/rtlil.h"
#include "kernel/log.h"
#include <assert.h>
#include <set>
struct SigPool
{
typedef std::pair<RTLIL::Wire*,int> bitDef_t;
std::set<bitDef_t> bits;
void clear()
{
bits.clear();
}
void add(RTLIL::SigSpec sig)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
bits.insert(bit);
}
}
void add(const SigPool &other)
{
for (auto &bit : other.bits)
bits.insert(bit);
}
void del(RTLIL::SigSpec sig)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
bits.erase(bit);
}
}
void del(const SigPool &other)
{
for (auto &bit : other.bits)
bits.insert(bit);
}
void expand(RTLIL::SigSpec from, RTLIL::SigSpec to)
{
from.expand();
to.expand();
assert(from.chunks.size() == to.chunks.size());
for (size_t i = 0; i < from.chunks.size(); i++) {
bitDef_t bit_from(from.chunks[i].wire, from.chunks[i].offset);
bitDef_t bit_to(to.chunks[i].wire, to.chunks[i].offset);
if (bit_from.first == NULL || bit_to.first == NULL)
continue;
if (bits.count(bit_from) > 0)
bits.insert(bit_to);
}
}
RTLIL::SigSpec extract(RTLIL::SigSpec sig)
{
RTLIL::SigSpec result;
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
bitDef_t bit(c.wire, c.offset);
if (bits.count(bit) > 0)
result.append(c);
}
return result;
}
RTLIL::SigSpec remove(RTLIL::SigSpec sig)
{
RTLIL::SigSpec result;
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
bitDef_t bit(c.wire, c.offset);
if (bits.count(bit) == 0)
result.append(c);
}
return result;
}
bool check_any(RTLIL::SigSpec sig)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
bitDef_t bit(c.wire, c.offset);
if (bits.count(bit) != 0)
return true;
}
return false;
}
bool check_all(RTLIL::SigSpec sig)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
bitDef_t bit(c.wire, c.offset);
if (bits.count(bit) == 0)
return false;
}
return true;
}
};
template <typename T>
struct SigSet
{
typedef std::pair<RTLIL::Wire*,int> bitDef_t;
std::map<bitDef_t, std::set<T>> bits;
void clear()
{
bits.clear();
}
void insert(RTLIL::SigSpec sig, T data)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
bits[bit].insert(data);
}
}
void erase(RTLIL::SigSpec sig)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
bits[bit].clear();
}
}
void erase(RTLIL::SigSpec sig, T data)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
bits[bit].erase(data);
}
}
void find(RTLIL::SigSpec sig, std::set<T> &result)
{
sig.expand();
for (auto &c : sig.chunks) {
if (c.wire == NULL)
continue;
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
for (auto &data : bits[bit])
result.insert(data);
}
}
std::set<T> find(RTLIL::SigSpec sig)
{
std::set<T> result;
find(sig, result);
return result;
}
};
struct SigMap
{
typedef std::pair<RTLIL::Wire*,int> bitDef_t;
struct shared_bit_data_t {
RTLIL::SigChunk chunk;
std::set<bitDef_t> bits;
};
std::map<bitDef_t, shared_bit_data_t*> bits;
SigMap(RTLIL::Module *module = NULL)
{
if (module != NULL)
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]->chunk = bit.second->chunk;
bits[bit.first]->bits = bit.second->bits;
}
}
void swap(SigMap &other)
{
bits.swap(other.bits);
}
~SigMap()
{
clear();
}
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();
}
void set(RTLIL::Module *module)
{
clear();
for (auto &it : module->connections)
add(it.first, it.second);
}
// internal helper function
void register_bit(const RTLIL::SigChunk &c)
{
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
if (c.wire && bits.count(bit) == 0) {
shared_bit_data_t *bd = new shared_bit_data_t;
bd->chunk = c;
bd->bits.insert(bit);
bits[bit] = bd;
}
}
// internal helper function
void unregister_bit(const RTLIL::SigChunk &c)
{
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
if (c.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::SigChunk &c1, const RTLIL::SigChunk &c2)
{
assert(c1.wire != NULL && c2.wire != NULL);
assert(c1.width == 1 && c2.width == 1);
bitDef_t b1(c1.wire, c1.offset);
bitDef_t b2(c2.wire, c2.offset);
shared_bit_data_t *bd1 = bits[b1];
shared_bit_data_t *bd2 = bits[b2];
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->chunk = bd2->chunk;
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::SigChunk &c1, const RTLIL::SigChunk &c2)
{
assert(c1.wire != NULL);
assert(c1.width == 1 && c2.width == 1);
bitDef_t bit(c1.wire, c1.offset);
assert(bits.count(bit) > 0);
bits[bit]->chunk = c2;
}
// internal helper function
void map_bit(RTLIL::SigChunk &c)
{
assert(c.width == 1);
bitDef_t bit(c.wire, c.offset);
if (c.wire && bits.count(bit) > 0)
c = bits[bit]->chunk;
}
void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
{
from.expand();
to.expand();
assert(from.chunks.size() == to.chunks.size());
for (size_t i = 0; i < from.chunks.size(); i++)
{
RTLIL::SigChunk &cf = from.chunks[i];
RTLIL::SigChunk &ct = to.chunks[i];
if (cf.wire == NULL)
continue;
register_bit(cf);
register_bit(ct);
if (ct.wire != NULL)
merge_bit(cf, ct);
else
set_bit(cf, ct);
}
}
void add(RTLIL::SigSpec sig)
{
sig.expand();
for (size_t i = 0; i < sig.chunks.size(); i++)
{
RTLIL::SigChunk &c = sig.chunks[i];
if (c.wire != NULL) {
register_bit(c);
set_bit(c, c);
}
}
}
void del(RTLIL::SigSpec sig)
{
sig.expand();
for (auto &c : sig.chunks)
unregister_bit(c);
}
void apply(RTLIL::SigSpec &sig)
{
sig.expand();
for (auto &c : sig.chunks)
map_bit(c);
sig.optimize();
}
RTLIL::SigSpec operator()(RTLIL::SigSpec sig)
{
apply(sig);
return sig;
}
};
#endif /* SIGTOOLS_H */