2012-04-13 03:08:20 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 13:35:28 +02:00
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Large 4-state numbers
|
|
|
|
|
//
|
2019-11-08 04:33:59 +01:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2021-01-01 16:29:54 +01:00
|
|
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
2020-03-21 16:24:24 +01:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 23:07:57 +02:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2020-03-21 16:24:24 +01:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
2019-10-05 02:17:11 +02:00
|
|
|
|
2021-03-04 03:57:07 +01:00
|
|
|
#ifndef VERILATOR_V3NUMBER_H_
|
|
|
|
|
#define VERILATOR_V3NUMBER_H_
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2006-12-18 20:20:45 +01:00
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
#include "V3Error.h"
|
2021-05-21 15:34:27 +02:00
|
|
|
#include "V3Hash.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-04-02 01:23:52 +02:00
|
|
|
#include <cmath>
|
|
|
|
|
#include <limits>
|
2018-10-14 19:43:24 +02:00
|
|
|
#include <vector>
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//============================================================================
|
|
|
|
|
|
2020-04-02 01:23:52 +02:00
|
|
|
// Return if two numbers within Epsilon of each other
|
|
|
|
|
inline bool v3EpsilonEqual(double a, double b) {
|
2021-03-27 04:22:52 +01:00
|
|
|
return std::fabs(a - b)
|
|
|
|
|
<= (std::numeric_limits<double>::epsilon() * std::max(1.0, std::max(a, b)));
|
2020-04-02 01:23:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
|
|
2019-05-10 02:03:19 +02:00
|
|
|
class AstNode;
|
2021-06-30 14:20:56 +02:00
|
|
|
class FileLine;
|
|
|
|
|
|
|
|
|
|
// Holds a few entries of ValueAndX to avoid dynamic allocation in std::vector for less width of
|
|
|
|
|
// constants
|
|
|
|
|
class V3NumberData final {
|
|
|
|
|
public:
|
|
|
|
|
// TYPES
|
|
|
|
|
struct ValueAndX final {
|
|
|
|
|
// Value, with bit 0 in bit 0 of this vector (unless X/Z)
|
|
|
|
|
uint32_t m_value;
|
|
|
|
|
// Each bit is true if it's X or Z, 10=z, 11=x
|
|
|
|
|
uint32_t m_valueX;
|
|
|
|
|
bool operator==(const ValueAndX& other) const {
|
|
|
|
|
return m_value == other.m_value && m_valueX == other.m_valueX;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// MEMBERS
|
|
|
|
|
static constexpr size_t m_inlinedSize = 2; // Can hold 64 bit without dynamic allocation
|
|
|
|
|
ValueAndX m_inlined[m_inlinedSize]; // Holds the beginning m_inlinedSize words
|
|
|
|
|
std::vector<ValueAndX> m_data; // Holds m_inlinedSize-th word and later
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// CONSTRUCTORS
|
|
|
|
|
V3NumberData() {
|
|
|
|
|
for (size_t i = 0; i < m_inlinedSize; ++i) m_inlined[i] = {0, 0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
void ensureSizeAtLeast(size_t s) {
|
|
|
|
|
if (VL_UNLIKELY(s > m_data.size() + m_inlinedSize)) m_data.resize(s - m_inlinedSize);
|
|
|
|
|
}
|
|
|
|
|
ValueAndX& operator[](size_t idx) {
|
|
|
|
|
UDEBUGONLY(UASSERT(idx < m_data.size() + m_inlinedSize,
|
|
|
|
|
"idx:" << idx << " size:" << m_data.size()
|
|
|
|
|
<< " inlinedSize:" << m_inlinedSize););
|
|
|
|
|
return idx >= m_inlinedSize ? m_data[idx - m_inlinedSize] : m_inlined[idx];
|
|
|
|
|
}
|
|
|
|
|
const ValueAndX& operator[](size_t idx) const { return const_cast<V3NumberData&>(*this)[idx]; }
|
|
|
|
|
};
|
2019-05-10 02:03:19 +02:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class V3Number final {
|
2021-06-30 14:20:56 +02:00
|
|
|
// TYPES
|
|
|
|
|
using ValueAndX = V3NumberData::ValueAndX;
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
// Large 4-state number handling
|
2020-04-15 13:58:34 +02:00
|
|
|
int m_width; // Width as specified/calculated.
|
|
|
|
|
bool m_sized : 1; // True if the user specified the width, else we track it.
|
|
|
|
|
bool m_signed : 1; // True if signed value
|
|
|
|
|
bool m_double : 1; // True if double real value
|
2020-12-05 22:49:10 +01:00
|
|
|
bool m_isNull : 1; // True if "null" versus normal 0
|
2020-04-15 13:58:34 +02:00
|
|
|
bool m_isString : 1; // True if string
|
|
|
|
|
bool m_fromString : 1; // True if from string literal
|
|
|
|
|
bool m_autoExtend : 1; // True if SystemVerilog extend-to-any-width
|
|
|
|
|
FileLine* m_fileline;
|
|
|
|
|
AstNode* m_nodep; // Parent node
|
2021-06-30 14:20:56 +02:00
|
|
|
V3NumberData m_value; // Value and X/Z information
|
2020-04-15 13:58:34 +02:00
|
|
|
string m_stringVal; // If isString, the value of the string
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
|
|
|
|
V3Number& setSingleBits(char value);
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& setString(const string& str) {
|
|
|
|
|
m_isString = true;
|
|
|
|
|
m_stringVal = str;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
2017-04-27 00:34:01 +02:00
|
|
|
void opCleanThis(bool warnOnTruncation = false);
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2019-05-10 02:03:19 +02:00
|
|
|
void nodep(AstNode* nodep) { setNames(nodep); }
|
2019-06-12 00:31:06 +02:00
|
|
|
FileLine* fileline() const { return m_fileline; }
|
2009-10-06 03:09:26 +02:00
|
|
|
V3Number& setZero();
|
2006-08-26 13:35:28 +02:00
|
|
|
V3Number& setQuad(vluint64_t value);
|
|
|
|
|
V3Number& setLong(uint32_t value);
|
2011-07-24 01:58:34 +02:00
|
|
|
V3Number& setLongS(vlsint32_t value);
|
|
|
|
|
V3Number& setDouble(double value);
|
2018-08-25 15:52:45 +02:00
|
|
|
void setBit(int bit, char value) { // Note must be pre-zeroed!
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit >= m_width) return;
|
|
|
|
|
uint32_t mask = (1UL << (bit & 31));
|
2021-06-30 14:20:56 +02:00
|
|
|
ValueAndX& v = m_value[bit / 32];
|
2020-04-15 13:58:34 +02:00
|
|
|
if (value == '0' || value == 0) {
|
2021-06-30 14:20:56 +02:00
|
|
|
v.m_value &= ~mask;
|
|
|
|
|
v.m_valueX &= ~mask;
|
2020-04-15 13:58:34 +02:00
|
|
|
} else if (value == '1' || value == 1) {
|
2021-06-30 14:20:56 +02:00
|
|
|
v.m_value |= mask;
|
|
|
|
|
v.m_valueX &= ~mask;
|
2020-04-15 13:58:34 +02:00
|
|
|
} else if (value == 'z' || value == 2) {
|
2021-06-30 14:20:56 +02:00
|
|
|
v.m_value &= ~mask;
|
|
|
|
|
v.m_valueX |= mask;
|
2019-05-19 22:13:13 +02:00
|
|
|
} else { // X
|
2021-06-30 14:20:56 +02:00
|
|
|
v.m_value |= mask;
|
|
|
|
|
v.m_valueX |= mask;
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
private:
|
2018-08-25 15:52:45 +02:00
|
|
|
char bitIs(int bit) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit >= m_width || bit < 0) {
|
2019-05-19 22:13:13 +02:00
|
|
|
// We never sign extend
|
|
|
|
|
return '0';
|
|
|
|
|
}
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ("01zx"[(((v.m_value & (1UL << (bit & 31))) ? 1 : 0)
|
|
|
|
|
| ((v.m_valueX & (1UL << (bit & 31))) ? 2 : 0))]);
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2018-08-25 15:52:45 +02:00
|
|
|
char bitIsExtend(int bit, int lbits) const {
|
2019-05-19 22:13:13 +02:00
|
|
|
// lbits usually = width, but for C optimizations width=32_bits, lbits = 32_or_less
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit < 0) return '0';
|
|
|
|
|
UASSERT(lbits <= m_width, "Extend of wrong size");
|
|
|
|
|
if (bit >= lbits) {
|
|
|
|
|
bit = lbits ? lbits - 1 : 0;
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
2019-05-19 22:13:13 +02:00
|
|
|
// We do sign extend
|
2021-06-30 14:20:56 +02:00
|
|
|
return ("01zx"[(((v.m_value & (1UL << (bit & 31))) ? 1 : 0)
|
|
|
|
|
| ((v.m_valueX & (1UL << (bit & 31))) ? 2 : 0))]);
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ("01zx"[(((v.m_value & (1UL << (bit & 31))) ? 1 : 0)
|
|
|
|
|
| ((v.m_valueX & (1UL << (bit & 31))) ? 2 : 0))]);
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2021-01-16 15:47:04 +01:00
|
|
|
|
|
|
|
|
public:
|
2018-08-25 15:52:45 +02:00
|
|
|
bool bitIs0(int bit) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit < 0) return false;
|
|
|
|
|
if (bit >= m_width) return !bitIsXZ(m_width - 1);
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ((v.m_value & (1UL << (bit & 31))) == 0 && !(v.m_valueX & (1UL << (bit & 31))));
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2018-08-25 15:52:45 +02:00
|
|
|
bool bitIs1(int bit) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit < 0) return false;
|
|
|
|
|
if (bit >= m_width) return false;
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ((v.m_value & (1UL << (bit & 31))) && !(v.m_valueX & (1UL << (bit & 31))));
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2018-08-25 15:52:45 +02:00
|
|
|
bool bitIs1Extend(int bit) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit < 0) return false;
|
|
|
|
|
if (bit >= m_width) return bitIs1Extend(m_width - 1);
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ((v.m_value & (1UL << (bit & 31))) && !(v.m_valueX & (1UL << (bit & 31))));
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2018-08-25 15:52:45 +02:00
|
|
|
bool bitIsX(int bit) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit < 0) return false;
|
|
|
|
|
if (bit >= m_width) return bitIsZ(m_width - 1);
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ((v.m_value & (1UL << (bit & 31))) && (v.m_valueX & (1UL << (bit & 31))));
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
bool bitIsXZ(int bit) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit < 0) return false;
|
|
|
|
|
if (bit >= m_width) return bitIsXZ(m_width - 1);
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ((v.m_valueX & (1UL << (bit & 31))));
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2018-08-25 15:52:45 +02:00
|
|
|
bool bitIsZ(int bit) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (bit < 0) return false;
|
|
|
|
|
if (bit >= m_width) return bitIsZ(m_width - 1);
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[bit / 32];
|
|
|
|
|
return ((~v.m_value & (1UL << (bit & 31))) && (v.m_valueX & (1UL << (bit & 31))));
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2021-01-16 15:47:04 +01:00
|
|
|
|
|
|
|
|
private:
|
2007-06-14 16:24:21 +02:00
|
|
|
uint32_t bitsValue(int lsb, int nbits) const {
|
2019-05-19 22:13:13 +02:00
|
|
|
uint32_t v = 0;
|
2020-04-15 13:58:34 +02:00
|
|
|
for (int bitn = 0; bitn < nbits; bitn++) { v |= (bitIs1(lsb + bitn) << bitn); }
|
2019-05-19 22:13:13 +02:00
|
|
|
return v;
|
2007-06-14 16:24:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
int words() const { return ((width() + 31) / 32); }
|
2014-04-09 02:28:16 +02:00
|
|
|
uint32_t hiWordMask() const { return VL_MASK_I(width()); }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2009-10-27 01:12:09 +01:00
|
|
|
V3Number& opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool is_modulus);
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
|
|
|
|
// CONSTRUCTORS
|
2019-05-10 02:03:19 +02:00
|
|
|
explicit V3Number(AstNode* nodep) { init(nodep, 1); }
|
|
|
|
|
V3Number(AstNode* nodep, int width) { init(nodep, width); } // 0=unsized
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number(AstNode* nodep, int width, uint32_t value, bool sized = true) {
|
|
|
|
|
init(nodep, width, sized);
|
2021-06-30 14:20:56 +02:00
|
|
|
m_value[0].m_value = value;
|
2020-04-15 13:58:34 +02:00
|
|
|
opCleanThis();
|
2019-05-10 02:03:19 +02:00
|
|
|
}
|
|
|
|
|
// Create from a verilog 32'hxxxx number.
|
2020-08-15 16:12:55 +02:00
|
|
|
V3Number(AstNode* nodep, const char* sourcep) { V3NumberCreate(nodep, sourcep, nullptr); }
|
2019-05-10 02:03:19 +02:00
|
|
|
class FileLined {}; // Fileline based errors, for parsing only, otherwise pass nodep
|
2020-08-15 16:12:55 +02:00
|
|
|
V3Number(FileLined, FileLine* fl, const char* sourcep) {
|
|
|
|
|
V3NumberCreate(nullptr, sourcep, fl);
|
|
|
|
|
}
|
2018-10-15 00:39:33 +02:00
|
|
|
class VerilogStringLiteral {}; // For creator type-overload selection
|
2019-05-10 02:03:19 +02:00
|
|
|
V3Number(VerilogStringLiteral, AstNode* nodep, const string& str);
|
2014-11-28 21:01:50 +01:00
|
|
|
class String {};
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number(String, AstNode* nodep, const string& value) {
|
|
|
|
|
init(nodep, 0);
|
|
|
|
|
setString(value);
|
|
|
|
|
}
|
2020-12-05 22:49:10 +01:00
|
|
|
class Null {};
|
|
|
|
|
V3Number(Null, AstNode* nodep) {
|
|
|
|
|
init(nodep, 0);
|
|
|
|
|
m_isNull = true;
|
|
|
|
|
m_autoExtend = true;
|
|
|
|
|
}
|
2020-02-04 05:21:56 +01:00
|
|
|
explicit V3Number(const V3Number* nump, int width = 1) {
|
2020-08-15 16:12:55 +02:00
|
|
|
init(nullptr, width);
|
2019-05-10 02:03:19 +02:00
|
|
|
m_fileline = nump->fileline();
|
|
|
|
|
}
|
|
|
|
|
V3Number(const V3Number* nump, int width, uint32_t value) {
|
2020-08-15 16:12:55 +02:00
|
|
|
init(nullptr, width);
|
2021-06-30 14:20:56 +02:00
|
|
|
m_value[0].m_value = value;
|
2019-05-10 02:03:19 +02:00
|
|
|
opCleanThis();
|
|
|
|
|
m_fileline = nump->fileline();
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2011-08-05 03:58:45 +02:00
|
|
|
private:
|
2019-05-10 02:03:19 +02:00
|
|
|
void V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl);
|
2020-04-15 13:58:34 +02:00
|
|
|
void init(AstNode* nodep, int swidth, bool sized = true) {
|
2019-05-10 02:03:19 +02:00
|
|
|
setNames(nodep);
|
2021-01-03 03:43:13 +01:00
|
|
|
// dtype info does NOT from nodep's dtype; nodep only for error reporting
|
2019-05-19 22:13:13 +02:00
|
|
|
m_signed = false;
|
|
|
|
|
m_double = false;
|
2020-12-05 22:49:10 +01:00
|
|
|
m_isNull = false;
|
2019-05-19 22:13:13 +02:00
|
|
|
m_isString = false;
|
|
|
|
|
m_autoExtend = false;
|
|
|
|
|
m_fromString = false;
|
2019-08-12 14:33:58 +02:00
|
|
|
width(swidth, sized);
|
2021-06-30 14:20:56 +02:00
|
|
|
for (int i = 0; i < words(); ++i) m_value[i] = {0, 0};
|
2011-08-05 03:58:45 +02:00
|
|
|
}
|
2019-05-10 02:03:19 +02:00
|
|
|
void setNames(AstNode* nodep);
|
2020-01-15 13:32:45 +01:00
|
|
|
static string displayPad(size_t fmtsize, char pad, bool left, const string& in);
|
2019-05-10 02:03:19 +02:00
|
|
|
string displayed(FileLine* fl, const string& vformat) const;
|
2020-04-15 13:58:34 +02:00
|
|
|
string displayed(const string& vformat) const { return displayed(m_fileline, vformat); }
|
|
|
|
|
|
2011-08-05 03:58:45 +02:00
|
|
|
public:
|
2019-06-15 13:43:45 +02:00
|
|
|
void v3errorEnd(std::ostringstream& sstr) const;
|
2020-05-05 01:57:21 +02:00
|
|
|
void v3errorEndFatal(std::ostringstream& sstr) const VL_ATTR_NORETURN;
|
2020-04-15 13:58:34 +02:00
|
|
|
void width(int width, bool sized = true) {
|
2019-05-19 22:13:13 +02:00
|
|
|
// Set width. Only set m_width here, as we need to tweak vector size
|
2020-04-15 13:58:34 +02:00
|
|
|
if (width) {
|
|
|
|
|
m_sized = sized;
|
|
|
|
|
m_width = width;
|
|
|
|
|
} else {
|
|
|
|
|
m_sized = false;
|
|
|
|
|
m_width = 1;
|
|
|
|
|
}
|
2021-06-30 14:20:56 +02:00
|
|
|
m_value.ensureSizeAtLeast(words());
|
2011-08-05 03:58:45 +02:00
|
|
|
}
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
// SETTERS
|
2014-06-10 04:27:04 +02:00
|
|
|
V3Number& setAllBitsXRemoved();
|
2006-08-26 13:35:28 +02:00
|
|
|
V3Number& setAllBitsX();
|
|
|
|
|
V3Number& setAllBitsZ();
|
2009-01-06 17:03:57 +01:00
|
|
|
V3Number& setAllBits0();
|
|
|
|
|
V3Number& setAllBits1();
|
2007-03-09 16:18:56 +01:00
|
|
|
V3Number& setMask(int nbits); // IE if nbits=1, then 0b1, if 2->0b11, if 3->0b111 etc
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// ACCESSORS
|
2020-04-15 13:58:34 +02:00
|
|
|
string ascii(bool prefixed = true, bool cleanVerilog = false) const;
|
2019-05-10 02:03:19 +02:00
|
|
|
string displayed(AstNode* nodep, const string& vformat) const;
|
2020-05-12 04:13:59 +02:00
|
|
|
static bool displayedFmtLegal(char format, bool isScan); // Is this a valid format letter?
|
2006-08-26 13:35:28 +02:00
|
|
|
int width() const { return m_width; }
|
2019-05-10 02:03:19 +02:00
|
|
|
int widthMin() const; // Minimum width that can represent this number (~== log2(num)+1)
|
2006-08-26 13:35:28 +02:00
|
|
|
bool sized() const { return m_sized; }
|
|
|
|
|
bool autoExtend() const { return m_autoExtend; }
|
2008-09-23 01:36:08 +02:00
|
|
|
bool isFromString() const { return m_fromString; }
|
2020-04-15 13:58:34 +02:00
|
|
|
// Only correct for parsing of numbers from strings, otherwise not used
|
|
|
|
|
// (use AstConst::isSigned())
|
|
|
|
|
bool isSigned() const { return m_signed; }
|
|
|
|
|
// Only correct for parsing of numbers from strings, otherwise not used
|
|
|
|
|
// (use AstConst::isSigned())
|
|
|
|
|
bool isDouble() const { return m_double; }
|
|
|
|
|
// Only if have 64 bit value loaded, and want to indicate it's real
|
|
|
|
|
void isDouble(bool flag) { m_double = flag; }
|
2014-11-28 21:01:50 +01:00
|
|
|
bool isString() const { return m_isString; }
|
2020-04-15 13:58:34 +02:00
|
|
|
void isString(bool flag) { m_isString = flag; }
|
|
|
|
|
bool isNegative() const { return bitIs1(width() - 1); }
|
2020-12-05 22:49:10 +01:00
|
|
|
bool isNull() const { return m_isNull; }
|
2019-10-05 01:13:39 +02:00
|
|
|
bool isFourState() const;
|
2019-05-19 22:13:13 +02:00
|
|
|
bool hasZ() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
for (int i = 0; i < words(); i++) {
|
2021-06-30 14:20:56 +02:00
|
|
|
const ValueAndX v = m_value[i];
|
|
|
|
|
if ((~v.m_value) & v.m_valueX) return true;
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2021-08-18 20:15:02 +02:00
|
|
|
bool isAllZ() const;
|
|
|
|
|
bool isAllX() const;
|
2006-08-26 13:35:28 +02:00
|
|
|
bool isEqZero() const;
|
|
|
|
|
bool isNeqZero() const;
|
2011-03-12 13:45:04 +01:00
|
|
|
bool isBitsZero(int msb, int lsb) const;
|
2006-08-26 13:35:28 +02:00
|
|
|
bool isEqOne() const;
|
2020-04-15 13:58:34 +02:00
|
|
|
bool isEqAllOnes(int optwidth = 0) const;
|
2018-10-15 00:39:33 +02:00
|
|
|
bool isCaseEq(const V3Number& rhs) const; // operator==
|
|
|
|
|
bool isLtXZ(const V3Number& rhs) const; // operator< with XZ compared
|
2019-05-19 22:13:13 +02:00
|
|
|
void isSigned(bool ssigned) { m_signed = ssigned; }
|
2020-05-08 03:04:26 +02:00
|
|
|
bool isAnyX() const;
|
|
|
|
|
bool isAnyXZ() const;
|
2020-11-28 03:34:40 +01:00
|
|
|
bool isAnyZ() const;
|
2019-05-08 03:57:38 +02:00
|
|
|
bool isMsbXZ() const { return bitIsXZ(m_width); }
|
2008-09-03 23:40:01 +02:00
|
|
|
uint32_t toUInt() const;
|
|
|
|
|
vlsint32_t toSInt() const;
|
|
|
|
|
vluint64_t toUQuad() const;
|
|
|
|
|
vlsint64_t toSQuad() const;
|
2010-01-18 01:13:44 +01:00
|
|
|
string toString() const;
|
2017-12-03 04:10:58 +01:00
|
|
|
string toDecimalS() const; // return ASCII signed decimal number
|
|
|
|
|
string toDecimalU() const; // return ASCII unsigned decimal number
|
2011-07-24 01:58:34 +02:00
|
|
|
double toDouble() const;
|
2021-05-21 15:34:27 +02:00
|
|
|
V3Hash toHash() const;
|
2019-12-09 03:36:38 +01:00
|
|
|
uint32_t edataWord(int eword) const;
|
|
|
|
|
uint8_t dataByte(int byte) const;
|
2020-05-10 20:27:22 +02:00
|
|
|
uint32_t countBits(const V3Number& ctrl) const;
|
|
|
|
|
uint32_t countBits(const V3Number& ctrl1, const V3Number& ctrl2, const V3Number& ctrl3) const;
|
2006-08-26 13:35:28 +02:00
|
|
|
uint32_t countOnes() const;
|
2020-04-15 13:58:34 +02:00
|
|
|
uint32_t
|
|
|
|
|
mostSetBitP1() const; // Highest bit set plus one, IE for 16 return 5, for 0 return 0.
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2009-12-18 02:58:14 +01:00
|
|
|
// Operators
|
2013-02-02 18:43:28 +01:00
|
|
|
bool operator<(const V3Number& rhs) const { return isLtXZ(rhs); }
|
2009-12-18 02:58:14 +01:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
// STATICS
|
|
|
|
|
static int log2b(uint32_t num);
|
|
|
|
|
|
2021-03-13 00:10:45 +01:00
|
|
|
using UniopFuncp = V3Number& (*)(V3Number&);
|
|
|
|
|
using BiopFuncp = V3Number& (*)(V3Number&, V3Number&);
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// MATH
|
|
|
|
|
// "this" is the output, as we need the output width before some computations
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& isTrue(const V3Number& lhs);
|
2019-05-19 22:13:13 +02:00
|
|
|
V3Number& opBitsNonX(const V3Number& lhs); // 0/1->1, X/Z->0
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opBitsOne(const V3Number& lhs); // 1->1, 0/X/Z->0
|
|
|
|
|
V3Number& opBitsXZ(const V3Number& lhs); // 0/1->0, X/Z->1
|
|
|
|
|
V3Number& opBitsZ(const V3Number& lhs); // Z->1, 0/1/X->0
|
2019-05-19 22:13:13 +02:00
|
|
|
V3Number& opBitsNonZ(const V3Number& lhs); // Z->0, 0/1/X->1
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opAssign(const V3Number& lhs);
|
2020-04-05 17:56:15 +02:00
|
|
|
V3Number& opAssignNonXZ(const V3Number& lhs, bool ignoreXZ = true);
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opExtendS(const V3Number& lhs, uint32_t lbits); // Sign extension
|
2019-05-08 03:57:38 +02:00
|
|
|
V3Number& opExtendXZ(const V3Number& lhs, uint32_t lbits); // X/Z extension
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opRedOr(const V3Number& lhs);
|
|
|
|
|
V3Number& opRedAnd(const V3Number& lhs);
|
|
|
|
|
V3Number& opRedXor(const V3Number& lhs);
|
2020-05-10 20:27:22 +02:00
|
|
|
V3Number& opCountBits(const V3Number& expr, const V3Number& ctrl1, const V3Number& ctrl2,
|
|
|
|
|
const V3Number& ctrl3);
|
2006-08-26 13:35:28 +02:00
|
|
|
V3Number& opCountOnes(const V3Number& lhs);
|
|
|
|
|
V3Number& opIsUnknown(const V3Number& lhs);
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opOneHot(const V3Number& lhs);
|
|
|
|
|
V3Number& opOneHot0(const V3Number& lhs);
|
|
|
|
|
V3Number& opCLog2(const V3Number& lhs);
|
|
|
|
|
V3Number& opClean(const V3Number& lhs, uint32_t bits);
|
|
|
|
|
V3Number& opConcat(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLenN(const V3Number& lhs);
|
|
|
|
|
V3Number& opRepl(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opRepl(const V3Number& lhs, uint32_t rhsval);
|
|
|
|
|
V3Number& opStreamL(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opSel(const V3Number& lhs, const V3Number& msb, const V3Number& lsb);
|
|
|
|
|
V3Number& opSel(const V3Number& lhs, uint32_t msbval, uint32_t lsbval);
|
|
|
|
|
V3Number& opSelInto(const V3Number& lhs, const V3Number& lsb, int width);
|
|
|
|
|
V3Number& opSelInto(const V3Number& lhs, int lsbval, int width);
|
2019-11-17 11:05:09 +01:00
|
|
|
V3Number& opToLowerN(const V3Number& lhs);
|
|
|
|
|
V3Number& opToUpperN(const V3Number& lhs);
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opCaseEq(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opCaseNeq(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opWildEq(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opWildNeq(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opBufIf1(const V3Number& ens, const V3Number& if1s);
|
2006-08-26 13:35:28 +02:00
|
|
|
// "standard" math
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opNot(const V3Number& lhs);
|
|
|
|
|
V3Number& opLogNot(const V3Number& lhs);
|
|
|
|
|
V3Number& opLogAnd(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLogOr(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLogEq(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLogIf(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opNegate(const V3Number& lhs);
|
|
|
|
|
V3Number& opAdd(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opSub(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opMul(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opMulS(const V3Number& lhs, const V3Number& rhs); // Signed
|
|
|
|
|
V3Number& opDiv(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opDivS(const V3Number& lhs, const V3Number& rhs); // Signed
|
|
|
|
|
V3Number& opModDiv(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opModDivS(const V3Number& lhs, const V3Number& rhs); // Signed
|
|
|
|
|
V3Number& opPow(const V3Number& lhs, const V3Number& rhs, bool lsign = false,
|
|
|
|
|
bool rsign = false);
|
|
|
|
|
V3Number& opPowSU(const V3Number& lhs, const V3Number& rhs); // Signed lhs, unsigned rhs
|
|
|
|
|
V3Number& opPowSS(const V3Number& lhs, const V3Number& rhs); // Signed lhs, signed rhs
|
|
|
|
|
V3Number& opPowUS(const V3Number& lhs, const V3Number& rhs); // Unsigned lhs, signed rhs
|
|
|
|
|
V3Number& opAnd(const V3Number& lhs, const V3Number& rhs);
|
2006-08-26 13:35:28 +02:00
|
|
|
V3Number& opChangeXor(const V3Number& lhs, const V3Number& rhs);
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opXor(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opOr(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opShiftR(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opShiftRS(const V3Number& lhs, const V3Number& rhs, // Arithmetic w/carry
|
|
|
|
|
uint32_t lbits);
|
|
|
|
|
V3Number& opShiftL(const V3Number& lhs, const V3Number& rhs);
|
2006-08-26 13:35:28 +02:00
|
|
|
// Comparisons
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opEq(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opNeq(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opGt(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opGtS(const V3Number& lhs, const V3Number& rhs); // Signed
|
|
|
|
|
V3Number& opGte(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opGteS(const V3Number& lhs, const V3Number& rhs); // Signed
|
|
|
|
|
V3Number& opLt(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLtS(const V3Number& lhs, const V3Number& rhs); // Signed
|
|
|
|
|
V3Number& opLte(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLteS(const V3Number& lhs, const V3Number& rhs); // Signed
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2011-07-24 01:58:34 +02:00
|
|
|
// "D" - double (aka real) math
|
2020-08-07 03:56:43 +02:00
|
|
|
V3Number& opIToRD(const V3Number& lhs, bool isSigned = false);
|
|
|
|
|
V3Number& opISToRD(const V3Number& lhs) { return opIToRD(lhs, true); }
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opRToIS(const V3Number& lhs);
|
2019-05-19 22:13:13 +02:00
|
|
|
V3Number& opRToIRoundS(const V3Number& lhs);
|
|
|
|
|
V3Number& opRealToBits(const V3Number& lhs);
|
2011-07-24 01:58:34 +02:00
|
|
|
V3Number& opBitsToRealD(const V3Number& lhs);
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opNegateD(const V3Number& lhs);
|
|
|
|
|
V3Number& opAddD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opSubD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opMulD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opDivD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opPowD(const V3Number& lhs, const V3Number& rhs);
|
2011-07-24 01:58:34 +02:00
|
|
|
// Comparisons
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opEqD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opNeqD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opGtD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opGteD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLtD(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLteD(const V3Number& lhs, const V3Number& rhs);
|
2014-11-28 21:01:50 +01:00
|
|
|
|
|
|
|
|
// "N" - string operations
|
2020-04-15 13:58:34 +02:00
|
|
|
V3Number& opAtoN(const V3Number& lhs, int base);
|
|
|
|
|
V3Number& opPutcN(const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
|
|
|
|
V3Number& opGetcN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opSubstrN(const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
|
|
|
|
V3Number& opCompareNN(const V3Number& lhs, const V3Number& rhs, bool ignoreCase);
|
|
|
|
|
V3Number& opConcatN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opReplN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opReplN(const V3Number& lhs, uint32_t rhsval);
|
|
|
|
|
V3Number& opEqN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opNeqN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opGtN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opGteN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLtN(const V3Number& lhs, const V3Number& rhs);
|
|
|
|
|
V3Number& opLteN(const V3Number& lhs, const V3Number& rhs);
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
2020-04-15 13:58:34 +02:00
|
|
|
inline std::ostream& operator<<(std::ostream& os, const V3Number& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
#endif // Guard
|