113245Sgabeblack@google.com/*
213245Sgabeblack@google.com * Copyright 2018 Google, Inc.
313245Sgabeblack@google.com *
413245Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
513245Sgabeblack@google.com * modification, are permitted provided that the following conditions are
613245Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
713245Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
813245Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
913245Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1013245Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1113245Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1213245Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1313245Sgabeblack@google.com * this software without specific prior written permission.
1413245Sgabeblack@google.com *
1513245Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1613245Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1713245Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1813245Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1913245Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2013245Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2113245Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2213245Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2313245Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2413245Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2513245Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2613245Sgabeblack@google.com *
2713245Sgabeblack@google.com * Authors: Gabe Black
2813245Sgabeblack@google.com */
2913245Sgabeblack@google.com
3013245Sgabeblack@google.com#include "systemc/utils/vcd.hh"
3113245Sgabeblack@google.com
3213245Sgabeblack@google.com#include <ctime>
3313245Sgabeblack@google.com#include <iomanip>
3413245Sgabeblack@google.com
3513245Sgabeblack@google.com#include "base/bitfield.hh"
3613245Sgabeblack@google.com#include "base/cprintf.hh"
3713245Sgabeblack@google.com#include "systemc/core/scheduler.hh"
3813245Sgabeblack@google.com#include "systemc/ext/core/sc_event.hh"
3913245Sgabeblack@google.com#include "systemc/ext/core/sc_main.hh"
4013245Sgabeblack@google.com#include "systemc/ext/core/sc_time.hh"
4113245Sgabeblack@google.com#include "systemc/ext/dt/bit/sc_bv_base.hh"
4213245Sgabeblack@google.com#include "systemc/ext/dt/bit/sc_logic.hh"
4313245Sgabeblack@google.com#include "systemc/ext/dt/bit/sc_lv_base.hh"
4413245Sgabeblack@google.com#include "systemc/ext/dt/fx/sc_fxnum.hh"
4513245Sgabeblack@google.com#include "systemc/ext/dt/fx/sc_fxval.hh"
4613245Sgabeblack@google.com#include "systemc/ext/dt/int/sc_int_base.hh"
4713245Sgabeblack@google.com#include "systemc/ext/dt/int/sc_signed.hh"
4813245Sgabeblack@google.com#include "systemc/ext/dt/int/sc_uint_base.hh"
4913245Sgabeblack@google.com#include "systemc/ext/dt/int/sc_unsigned.hh"
5013245Sgabeblack@google.com#include "systemc/ext/utils/functions.hh"
5113245Sgabeblack@google.com
5213245Sgabeblack@google.comnamespace sc_gem5
5313245Sgabeblack@google.com{
5413245Sgabeblack@google.com
5513245Sgabeblack@google.comnamespace
5613245Sgabeblack@google.com{
5713245Sgabeblack@google.com
5813245Sgabeblack@google.comstd::string
5913245Sgabeblack@google.comcleanName(std::string name)
6013245Sgabeblack@google.com{
6113245Sgabeblack@google.com    for (int i = 0; i < name.length(); i++) {
6213245Sgabeblack@google.com        if (name[i] == '[')
6313245Sgabeblack@google.com            name[i] = '(';
6413245Sgabeblack@google.com        else if (name[i] == ']')
6513245Sgabeblack@google.com            name[i] = ')';
6613245Sgabeblack@google.com    }
6713245Sgabeblack@google.com    return name;
6813245Sgabeblack@google.com}
6913245Sgabeblack@google.com
7013245Sgabeblack@google.com} // anonymous namespace
7113245Sgabeblack@google.com
7213245Sgabeblack@google.comclass VcdTraceValBase : public TraceValBase
7313245Sgabeblack@google.com{
7413245Sgabeblack@google.com  protected:
7513245Sgabeblack@google.com    std::string _vcdName;
7613245Sgabeblack@google.com
7713245Sgabeblack@google.com    const char *
7813245Sgabeblack@google.com    stripLeadingBits(const char *orig)
7913245Sgabeblack@google.com    {
8013245Sgabeblack@google.com        const char first = orig[0];
8113245Sgabeblack@google.com
8213245Sgabeblack@google.com        if (first != 'z' && first != 'x' && first != '0')
8313245Sgabeblack@google.com            return orig;
8413245Sgabeblack@google.com
8513245Sgabeblack@google.com        const char *res = orig;
8613245Sgabeblack@google.com        while (*++res == first) {}
8713245Sgabeblack@google.com
8813245Sgabeblack@google.com        if (first != '0' || *res != '1')
8913245Sgabeblack@google.com            res--;
9013245Sgabeblack@google.com
9113245Sgabeblack@google.com        return res;
9213245Sgabeblack@google.com    }
9313245Sgabeblack@google.com
9413245Sgabeblack@google.com    char
9513245Sgabeblack@google.com    scLogicToVcdState(char in)
9613245Sgabeblack@google.com    {
9713245Sgabeblack@google.com        switch (in) {
9813245Sgabeblack@google.com          case 'U':
9913245Sgabeblack@google.com          case 'X':
10013245Sgabeblack@google.com          case 'W':
10113245Sgabeblack@google.com          case 'D':
10213245Sgabeblack@google.com            return 'x';
10313245Sgabeblack@google.com          case '0':
10413245Sgabeblack@google.com          case 'L':
10513245Sgabeblack@google.com            return '0';
10613245Sgabeblack@google.com          case '1':
10713245Sgabeblack@google.com          case 'H':
10813245Sgabeblack@google.com            return '1';
10913245Sgabeblack@google.com          case 'Z':
11013245Sgabeblack@google.com            return 'z';
11113245Sgabeblack@google.com          default:
11213245Sgabeblack@google.com            return '?';
11313245Sgabeblack@google.com        }
11413245Sgabeblack@google.com    }
11513245Sgabeblack@google.com
11613245Sgabeblack@google.com    void
11713245Sgabeblack@google.com    printVal(std::ostream &os, const std::string &rep)
11813245Sgabeblack@google.com    {
11913245Sgabeblack@google.com        switch (width()) {
12013245Sgabeblack@google.com          case 0:
12113245Sgabeblack@google.com            return;
12213245Sgabeblack@google.com          case 1:
12313245Sgabeblack@google.com            os << rep << vcdName() << std::endl;;
12413245Sgabeblack@google.com            return;
12513245Sgabeblack@google.com          default:
12613245Sgabeblack@google.com            os << "b" << stripLeadingBits(rep.c_str()) << " " <<
12713245Sgabeblack@google.com                vcdName() << std::endl;
12813245Sgabeblack@google.com            return;
12913245Sgabeblack@google.com        }
13013245Sgabeblack@google.com    }
13113245Sgabeblack@google.com
13213245Sgabeblack@google.com  public:
13313245Sgabeblack@google.com    VcdTraceValBase(int width) : TraceValBase(width) {}
13413245Sgabeblack@google.com    ~VcdTraceValBase() {}
13513245Sgabeblack@google.com
13613245Sgabeblack@google.com    void vcdName(const std::string &vcd_name) { _vcdName = vcd_name; }
13713245Sgabeblack@google.com    const std::string &vcdName() { return _vcdName; }
13813245Sgabeblack@google.com    virtual std::string vcdType() { return "wire"; }
13913245Sgabeblack@google.com
14013245Sgabeblack@google.com    virtual void output(std::ostream &os) = 0;
14113245Sgabeblack@google.com};
14213245Sgabeblack@google.com
14313245Sgabeblack@google.comvoid
14413245Sgabeblack@google.comVcdTraceScope::addValue(const std::string &name, VcdTraceValBase *value)
14513245Sgabeblack@google.com{
14613245Sgabeblack@google.com    size_t pos = name.find_first_of('.');
14713245Sgabeblack@google.com    if (pos == std::string::npos) {
14813245Sgabeblack@google.com        values.emplace_back(name, value);
14913245Sgabeblack@google.com    } else {
15013245Sgabeblack@google.com        std::string sname = name.substr(0, pos);
15113245Sgabeblack@google.com        auto it = scopes.find(sname);
15213245Sgabeblack@google.com        if (it == scopes.end())
15313245Sgabeblack@google.com            it = scopes.emplace(sname, new VcdTraceScope).first;
15413245Sgabeblack@google.com        it->second->addValue(name.substr(pos + 1), value);
15513245Sgabeblack@google.com    }
15613245Sgabeblack@google.com}
15713245Sgabeblack@google.com
15813245Sgabeblack@google.comvoid
15913245Sgabeblack@google.comVcdTraceScope::output(const std::string &name, std::ostream &os)
16013245Sgabeblack@google.com{
16113245Sgabeblack@google.com    os << "$scope module " << name << " $end" << std::endl;
16213245Sgabeblack@google.com
16313245Sgabeblack@google.com    for (auto &p: values) {
16413245Sgabeblack@google.com        const std::string &name = p.first;
16513245Sgabeblack@google.com        VcdTraceValBase *value = p.second;
16613245Sgabeblack@google.com
16713245Sgabeblack@google.com        int w = value->width();
16813245Sgabeblack@google.com        if (w <= 0) {
16913245Sgabeblack@google.com            std::string msg = csprintf("'%s' has 0 bits", name);
17013245Sgabeblack@google.com            // The typo in this error message is intentional to match the
17113245Sgabeblack@google.com            // Accellera output.
17213245Sgabeblack@google.com            SC_REPORT_ERROR("(E710) object cannot not be traced", msg.c_str());
17313245Sgabeblack@google.com            return;
17413245Sgabeblack@google.com        }
17513245Sgabeblack@google.com
17613245Sgabeblack@google.com        std::string clean_name = cleanName(name);
17713245Sgabeblack@google.com        if (w == 1) {
17813245Sgabeblack@google.com            ccprintf(os, "$var %s  % 3d  %s  %s       $end\n",
17913245Sgabeblack@google.com                     value->vcdType(), w, value->vcdName(), clean_name);
18013245Sgabeblack@google.com        } else {
18113245Sgabeblack@google.com            ccprintf(os, "$var %s  % 3d  %s  %s [%d:0]  $end\n",
18213245Sgabeblack@google.com                     value->vcdType(), w, value->vcdName(), clean_name, w - 1);
18313245Sgabeblack@google.com        }
18413245Sgabeblack@google.com    }
18513245Sgabeblack@google.com
18613245Sgabeblack@google.com    for (auto &p: scopes)
18713245Sgabeblack@google.com        p.second->output(p.first, os);
18813245Sgabeblack@google.com
18913245Sgabeblack@google.com    os << "$upscope $end" << std::endl;
19013245Sgabeblack@google.com}
19113245Sgabeblack@google.com
19213245Sgabeblack@google.comtemplate <typename T>
19313245Sgabeblack@google.comclass VcdTraceVal : public TraceVal<T, VcdTraceValBase>
19413245Sgabeblack@google.com{
19513245Sgabeblack@google.com  public:
19613245Sgabeblack@google.com    typedef T TracedType;
19713245Sgabeblack@google.com
19813245Sgabeblack@google.com    VcdTraceVal(const T* t, const std::string &vcd_name, int width) :
19913245Sgabeblack@google.com        TraceVal<T, VcdTraceValBase>(t, width)
20013245Sgabeblack@google.com    {
20113245Sgabeblack@google.com        this->vcdName(vcd_name);
20213245Sgabeblack@google.com    }
20313245Sgabeblack@google.com};
20413245Sgabeblack@google.com
20513245Sgabeblack@google.comstd::string
20613245Sgabeblack@google.comVcdTraceFile::nextSignalName()
20713245Sgabeblack@google.com{
20813245Sgabeblack@google.com    std::string name(_nextName);
20913245Sgabeblack@google.com
21013245Sgabeblack@google.com    bool carry = false;
21113245Sgabeblack@google.com    int pos = NextNameChars - 1;
21213245Sgabeblack@google.com    do {
21313245Sgabeblack@google.com        carry = (_nextName[pos] == 'z');
21413245Sgabeblack@google.com        if (carry)
21513245Sgabeblack@google.com            _nextName[pos--] = 'a';
21613245Sgabeblack@google.com        else
21713245Sgabeblack@google.com            _nextName[pos--]++;
21813245Sgabeblack@google.com    } while (carry && pos >= 0);
21913245Sgabeblack@google.com
22013245Sgabeblack@google.com    return name;
22113245Sgabeblack@google.com}
22213245Sgabeblack@google.com
22313245Sgabeblack@google.comvoid
22413245Sgabeblack@google.comVcdTraceFile::initialize()
22513245Sgabeblack@google.com{
22613245Sgabeblack@google.com    finalizeTime();
22713245Sgabeblack@google.com
22813245Sgabeblack@google.com    // Date.
22913245Sgabeblack@google.com    stream() << "$date" << std::endl;
23013245Sgabeblack@google.com    time_t long_time;
23113245Sgabeblack@google.com    time(&long_time);
23213245Sgabeblack@google.com    struct tm *p_tm = localtime(&long_time);
23313245Sgabeblack@google.com    stream() << std::put_time(p_tm, "     %b %d, %Y       %H:%M:%S\n");
23413245Sgabeblack@google.com    stream() << "$end" << std::endl << std::endl;
23513245Sgabeblack@google.com
23613245Sgabeblack@google.com    // Version.
23713245Sgabeblack@google.com    stream() << "$version" << std::endl;
23813245Sgabeblack@google.com    stream() << " " << ::sc_core::sc_version() << std::endl;
23913245Sgabeblack@google.com    stream() << "$end" << std::endl << std::endl;
24013245Sgabeblack@google.com
24113245Sgabeblack@google.com    // Timescale.
24213245Sgabeblack@google.com    stream() << "$timescale" << std::endl;
24313245Sgabeblack@google.com    stream() << "     " << ::sc_core::sc_time::from_value(timeUnitTicks) <<
24413245Sgabeblack@google.com        std::endl;
24513245Sgabeblack@google.com    stream() << "$end" << std::endl << std::endl;
24613245Sgabeblack@google.com
24713245Sgabeblack@google.com    for (auto tv: traceVals)
24813245Sgabeblack@google.com        tv->finalize();
24913245Sgabeblack@google.com
25013245Sgabeblack@google.com    topScope.output("SystemC", stream());
25113245Sgabeblack@google.com
25213245Sgabeblack@google.com    stream() << "$enddefinitions  $end" << std::endl << std::endl;
25313245Sgabeblack@google.com
25413245Sgabeblack@google.com    Tick now = scheduler.getCurTick();
25513245Sgabeblack@google.com
25613245Sgabeblack@google.com    std::string timedump_comment =
25713245Sgabeblack@google.com        csprintf("All initial values are dumped below at time "
25813245Sgabeblack@google.com                 "%g sec = %g timescale units.",
25913245Sgabeblack@google.com                 static_cast<double>(now) / SimClock::Float::s,
26013245Sgabeblack@google.com                 static_cast<double>(now / timeUnitTicks));
26113245Sgabeblack@google.com    writeComment(timedump_comment);
26213245Sgabeblack@google.com
26313245Sgabeblack@google.com    lastPrintedTime = now / timeUnitTicks;
26413245Sgabeblack@google.com
26513245Sgabeblack@google.com    stream() << "$dumpvars" << std::endl;
26613245Sgabeblack@google.com    for (auto tv: traceVals)
26713245Sgabeblack@google.com        tv->output(stream());
26813245Sgabeblack@google.com    stream() << "$end" << std::endl << std::endl;
26913245Sgabeblack@google.com
27013245Sgabeblack@google.com    initialized = true;
27113245Sgabeblack@google.com}
27213245Sgabeblack@google.com
27313245Sgabeblack@google.comVcdTraceFile::~VcdTraceFile()
27413245Sgabeblack@google.com{
27513245Sgabeblack@google.com    for (auto tv: traceVals)
27613245Sgabeblack@google.com        delete tv;
27713245Sgabeblack@google.com    traceVals.clear();
27813245Sgabeblack@google.com
27913245Sgabeblack@google.com    if (timeUnitTicks)
28013245Sgabeblack@google.com        ccprintf(stream(), "#%u\n", scheduler.getCurTick() / timeUnitTicks);
28113245Sgabeblack@google.com}
28213245Sgabeblack@google.com
28313245Sgabeblack@google.comvoid
28413245Sgabeblack@google.comVcdTraceFile::trace(bool delta)
28513245Sgabeblack@google.com{
28613245Sgabeblack@google.com    if (!delta)
28713245Sgabeblack@google.com        deltasAtNow = 0;
28813245Sgabeblack@google.com
28913245Sgabeblack@google.com    uint64_t deltaOffset = deltasAtNow;
29013245Sgabeblack@google.com
29113245Sgabeblack@google.com    if (delta)
29213245Sgabeblack@google.com        deltaOffset = deltasAtNow++;
29313245Sgabeblack@google.com
29413245Sgabeblack@google.com    if (_traceDeltas != delta)
29513245Sgabeblack@google.com        return;
29613245Sgabeblack@google.com
29713245Sgabeblack@google.com    if (!initialized) {
29813245Sgabeblack@google.com        initialize();
29913245Sgabeblack@google.com        return;
30013245Sgabeblack@google.com    }
30113245Sgabeblack@google.com
30213245Sgabeblack@google.com    Tick now = scheduler.getCurTick() / timeUnitTicks + deltaOffset;
30313245Sgabeblack@google.com
30413245Sgabeblack@google.com    if (now <= lastPrintedTime) {
30513245Sgabeblack@google.com        // TODO warn about reversed time?
30613245Sgabeblack@google.com        return;
30713245Sgabeblack@google.com    }
30813245Sgabeblack@google.com
30913245Sgabeblack@google.com    bool time_printed = false;
31013245Sgabeblack@google.com    for (auto tv: traceVals) {
31113245Sgabeblack@google.com        if (tv->check()) {
31213245Sgabeblack@google.com            if (!time_printed) {
31313245Sgabeblack@google.com                lastPrintedTime = now;
31413245Sgabeblack@google.com                ccprintf(stream(), "#%u\n", now);
31513245Sgabeblack@google.com                time_printed = true;
31613245Sgabeblack@google.com            }
31713245Sgabeblack@google.com
31813245Sgabeblack@google.com            tv->output(stream());
31913245Sgabeblack@google.com        }
32013245Sgabeblack@google.com    }
32113245Sgabeblack@google.com    if (time_printed)
32213245Sgabeblack@google.com        stream() << std::endl;
32313245Sgabeblack@google.com}
32413245Sgabeblack@google.com
32513245Sgabeblack@google.comclass VcdTraceValBool : public VcdTraceVal<bool>
32613245Sgabeblack@google.com{
32713245Sgabeblack@google.com  public:
32813245Sgabeblack@google.com    using VcdTraceVal<bool>::VcdTraceVal;
32913245Sgabeblack@google.com
33013245Sgabeblack@google.com    void
33113245Sgabeblack@google.com    output(std::ostream &os) override
33213245Sgabeblack@google.com    {
33313245Sgabeblack@google.com        printVal(os, this->value() ? "1" : "0");
33413245Sgabeblack@google.com    }
33513245Sgabeblack@google.com};
33613245Sgabeblack@google.com
33713245Sgabeblack@google.comvoid
33813245Sgabeblack@google.comVcdTraceFile::addTraceVal(const bool *v, const std::string &name)
33913245Sgabeblack@google.com{
34013245Sgabeblack@google.com    addNewTraceVal<VcdTraceValBool>(v, name);
34113245Sgabeblack@google.com}
34213245Sgabeblack@google.com
34313245Sgabeblack@google.comtemplate <typename T>
34413245Sgabeblack@google.comclass VcdTraceValFloat : public VcdTraceVal<T>
34513245Sgabeblack@google.com{
34613245Sgabeblack@google.com  public:
34713245Sgabeblack@google.com    using VcdTraceVal<T>::VcdTraceVal;
34813245Sgabeblack@google.com
34913245Sgabeblack@google.com    std::string vcdType() override { return "real"; }
35013245Sgabeblack@google.com
35113245Sgabeblack@google.com    void
35213245Sgabeblack@google.com    output(std::ostream &os) override
35313245Sgabeblack@google.com    {
35413245Sgabeblack@google.com        ccprintf(os, "r%.16g %s\n", this->value(), this->vcdName());
35513245Sgabeblack@google.com    }
35613245Sgabeblack@google.com};
35713245Sgabeblack@google.com
35813245Sgabeblack@google.comvoid
35913245Sgabeblack@google.comVcdTraceFile::addTraceVal(const float *v, const std::string &name)
36013245Sgabeblack@google.com{
36113245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFloat<float>>(v, name);
36213245Sgabeblack@google.com}
36313245Sgabeblack@google.comvoid
36413245Sgabeblack@google.comVcdTraceFile::addTraceVal(const double *v, const std::string &name)
36513245Sgabeblack@google.com{
36613245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFloat<double>>(v, name);
36713245Sgabeblack@google.com}
36813245Sgabeblack@google.com
36913245Sgabeblack@google.comclass VcdTraceValScLogic : public VcdTraceVal<sc_dt::sc_logic>
37013245Sgabeblack@google.com{
37113245Sgabeblack@google.com  public:
37213245Sgabeblack@google.com    using VcdTraceVal<sc_dt::sc_logic>::VcdTraceVal;
37313245Sgabeblack@google.com
37413245Sgabeblack@google.com    void
37513245Sgabeblack@google.com    output(std::ostream &os) override
37613245Sgabeblack@google.com    {
37713245Sgabeblack@google.com        char str[2] = {
37813245Sgabeblack@google.com            scLogicToVcdState(value().to_char()),
37913245Sgabeblack@google.com            '\0'
38013245Sgabeblack@google.com        };
38113245Sgabeblack@google.com        printVal(os, str);
38213245Sgabeblack@google.com    }
38313245Sgabeblack@google.com};
38413245Sgabeblack@google.com
38513245Sgabeblack@google.comvoid
38613245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_logic *v, const std::string &name)
38713245Sgabeblack@google.com{
38813245Sgabeblack@google.com    addNewTraceVal<VcdTraceValScLogic>(v, name);
38913245Sgabeblack@google.com}
39013245Sgabeblack@google.com
39113245Sgabeblack@google.comtemplate <typename T>
39213245Sgabeblack@google.comclass VcdTraceValFinite : public VcdTraceVal<T>
39313245Sgabeblack@google.com{
39413245Sgabeblack@google.com  public:
39513245Sgabeblack@google.com    using VcdTraceVal<T>::VcdTraceVal;
39613245Sgabeblack@google.com
39713245Sgabeblack@google.com    void
39813245Sgabeblack@google.com    finalize() override
39913245Sgabeblack@google.com    {
40013245Sgabeblack@google.com        VcdTraceVal<T>::finalize();
40113245Sgabeblack@google.com        this->_width = this->value().length();
40213245Sgabeblack@google.com    }
40313245Sgabeblack@google.com
40413245Sgabeblack@google.com    void
40513245Sgabeblack@google.com    output(std::ostream &os) override
40613245Sgabeblack@google.com    {
40713245Sgabeblack@google.com        std::string str;
40813245Sgabeblack@google.com        const int w = this->width();
40913245Sgabeblack@google.com
41013245Sgabeblack@google.com        str.reserve(w);
41113245Sgabeblack@google.com        for (int i = w - 1; i >= 0; i--)
41213245Sgabeblack@google.com            str += this->value()[i].to_bool() ? '1' : '0';
41313245Sgabeblack@google.com
41413245Sgabeblack@google.com        this->printVal(os, str);
41513245Sgabeblack@google.com    }
41613245Sgabeblack@google.com};
41713245Sgabeblack@google.com
41813245Sgabeblack@google.comvoid
41913245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_int_base *v,
42013245Sgabeblack@google.com                          const std::string &name)
42113245Sgabeblack@google.com{
42213245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFinite<sc_dt::sc_int_base>>(v, name);
42313245Sgabeblack@google.com}
42413245Sgabeblack@google.comvoid
42513245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_uint_base *v,
42613245Sgabeblack@google.com                          const std::string &name)
42713245Sgabeblack@google.com{
42813245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFinite<sc_dt::sc_uint_base>>(v, name);
42913245Sgabeblack@google.com}
43013245Sgabeblack@google.com
43113245Sgabeblack@google.comvoid
43213245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_signed *v, const std::string &name)
43313245Sgabeblack@google.com{
43413245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFinite<sc_dt::sc_signed>>(v, name);
43513245Sgabeblack@google.com}
43613245Sgabeblack@google.comvoid
43713245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_unsigned *v,
43813245Sgabeblack@google.com                          const std::string &name)
43913245Sgabeblack@google.com{
44013245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFinite<sc_dt::sc_unsigned>>(v, name);
44113245Sgabeblack@google.com}
44213245Sgabeblack@google.com
44313245Sgabeblack@google.comtemplate <typename T>
44413245Sgabeblack@google.comclass VcdTraceValLogic : public VcdTraceVal<T>
44513245Sgabeblack@google.com{
44613245Sgabeblack@google.com  public:
44713245Sgabeblack@google.com    using VcdTraceVal<T>::VcdTraceVal;
44813245Sgabeblack@google.com
44913245Sgabeblack@google.com    void
45013245Sgabeblack@google.com    finalize() override
45113245Sgabeblack@google.com    {
45213245Sgabeblack@google.com        VcdTraceVal<T>::finalize();
45313245Sgabeblack@google.com        this->_width = this->value().length();
45413245Sgabeblack@google.com    }
45513245Sgabeblack@google.com
45613245Sgabeblack@google.com    void
45713245Sgabeblack@google.com    output(std::ostream &os) override
45813245Sgabeblack@google.com    {
45913245Sgabeblack@google.com        this->printVal(os, this->value().to_string());
46013245Sgabeblack@google.com    }
46113245Sgabeblack@google.com};
46213245Sgabeblack@google.com
46313245Sgabeblack@google.comvoid
46413245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_bv_base *v, const std::string &name)
46513245Sgabeblack@google.com{
46613245Sgabeblack@google.com    addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_bv_base>>(v, name);
46713245Sgabeblack@google.com}
46813245Sgabeblack@google.comvoid
46913245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_lv_base *v, const std::string &name)
47013245Sgabeblack@google.com{
47113245Sgabeblack@google.com    addNewTraceVal<VcdTraceValLogic<::sc_dt::sc_lv_base>>(v, name);
47213245Sgabeblack@google.com}
47313245Sgabeblack@google.com
47413245Sgabeblack@google.comtemplate <typename T>
47513245Sgabeblack@google.comclass VcdTraceValFxval : public VcdTraceVal<T>
47613245Sgabeblack@google.com{
47713245Sgabeblack@google.com  public:
47813245Sgabeblack@google.com    using VcdTraceVal<T>::VcdTraceVal;
47913245Sgabeblack@google.com
48013245Sgabeblack@google.com    std::string vcdType() override { return "real"; }
48113245Sgabeblack@google.com
48213245Sgabeblack@google.com    void
48313245Sgabeblack@google.com    output(std::ostream &os) override
48413245Sgabeblack@google.com    {
48513245Sgabeblack@google.com        ccprintf(os, "r%.16g %s\n",
48613245Sgabeblack@google.com                this->value().to_double(), this->vcdName());
48713245Sgabeblack@google.com    }
48813245Sgabeblack@google.com};
48913245Sgabeblack@google.com
49013245Sgabeblack@google.comvoid
49113245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_fxval *v, const std::string &name)
49213245Sgabeblack@google.com{
49313245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval>>(v, name);
49413245Sgabeblack@google.com}
49513245Sgabeblack@google.comvoid
49613245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_fxval_fast *v,
49713245Sgabeblack@google.com                          const std::string &name)
49813245Sgabeblack@google.com{
49913245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFxval<sc_dt::sc_fxval_fast>>(v, name);
50013245Sgabeblack@google.com}
50113245Sgabeblack@google.com
50213245Sgabeblack@google.comtemplate <typename T>
50313245Sgabeblack@google.comclass VcdTraceValFxnum : public VcdTraceVal<T>
50413245Sgabeblack@google.com{
50513245Sgabeblack@google.com  public:
50613245Sgabeblack@google.com    using VcdTraceVal<T>::VcdTraceVal;
50713245Sgabeblack@google.com
50813245Sgabeblack@google.com    void
50913245Sgabeblack@google.com    output(std::ostream &os) override
51013245Sgabeblack@google.com    {
51113245Sgabeblack@google.com        std::string str;
51213245Sgabeblack@google.com        const int w = this->width();
51313245Sgabeblack@google.com
51413245Sgabeblack@google.com        str.reserve(w);
51513245Sgabeblack@google.com        for (int i = w - 1; i >= 0; i--)
51613245Sgabeblack@google.com            str += this->value()[i] ? '1' : '0';
51713245Sgabeblack@google.com
51813245Sgabeblack@google.com        this->printVal(os, str);
51913245Sgabeblack@google.com    }
52013245Sgabeblack@google.com};
52113245Sgabeblack@google.com
52213245Sgabeblack@google.comvoid
52313245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_fxnum *v, const std::string &name)
52413245Sgabeblack@google.com{
52513245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum>>(v, name);
52613245Sgabeblack@google.com}
52713245Sgabeblack@google.comvoid
52813245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::sc_fxnum_fast *v,
52913245Sgabeblack@google.com                          const std::string &name)
53013245Sgabeblack@google.com{
53113245Sgabeblack@google.com    addNewTraceVal<VcdTraceValFxnum<::sc_dt::sc_fxnum_fast>>(v, name);
53213245Sgabeblack@google.com}
53313245Sgabeblack@google.com
53413245Sgabeblack@google.comclass VcdTraceValEvent : public VcdTraceVal<::sc_core::sc_event>
53513245Sgabeblack@google.com{
53613245Sgabeblack@google.com  public:
53713245Sgabeblack@google.com    using VcdTraceVal<::sc_core::sc_event>::VcdTraceVal;
53813245Sgabeblack@google.com
53913245Sgabeblack@google.com    std::string vcdType() override { return "event"; }
54013245Sgabeblack@google.com
54113245Sgabeblack@google.com    void
54213245Sgabeblack@google.com    output(std::ostream &os) override
54313245Sgabeblack@google.com    {
54413245Sgabeblack@google.com        if (value())
54513245Sgabeblack@google.com            printVal(os, "1");
54613245Sgabeblack@google.com        else
54713245Sgabeblack@google.com            os << std::endl;
54813245Sgabeblack@google.com    }
54913245Sgabeblack@google.com};
55013245Sgabeblack@google.com
55113245Sgabeblack@google.comvoid
55213245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_core::sc_event *v, const std::string &name)
55313245Sgabeblack@google.com{
55413245Sgabeblack@google.com    addNewTraceVal<VcdTraceValEvent>(v, name);
55513245Sgabeblack@google.com}
55613245Sgabeblack@google.com
55713245Sgabeblack@google.comclass VcdTraceValTime : public VcdTraceVal<::sc_core::sc_time>
55813245Sgabeblack@google.com{
55913245Sgabeblack@google.com  private:
56013245Sgabeblack@google.com    static const int TimeWidth = 64;
56113245Sgabeblack@google.com
56213245Sgabeblack@google.com  public:
56313245Sgabeblack@google.com    using VcdTraceVal<::sc_core::sc_time>::VcdTraceVal;
56413245Sgabeblack@google.com
56513245Sgabeblack@google.com    std::string vcdType() override { return "time"; }
56613245Sgabeblack@google.com
56713245Sgabeblack@google.com    void
56813245Sgabeblack@google.com    finalize() override
56913245Sgabeblack@google.com    {
57013245Sgabeblack@google.com        VcdTraceVal<::sc_core::sc_time>::finalize();
57113245Sgabeblack@google.com        _width = TimeWidth;
57213245Sgabeblack@google.com    }
57313245Sgabeblack@google.com
57413245Sgabeblack@google.com    void
57513245Sgabeblack@google.com    output(std::ostream &os) override
57613245Sgabeblack@google.com    {
57713245Sgabeblack@google.com        char str[TimeWidth + 1];
57813245Sgabeblack@google.com        str[TimeWidth] = '\0';
57913245Sgabeblack@google.com
58013245Sgabeblack@google.com        const uint64_t val = value().value();
58113245Sgabeblack@google.com        for (int i = 0; i < TimeWidth; i++)
58213245Sgabeblack@google.com            str[i] = ::bits(val, TimeWidth - i - 1) ? '1' : '0';
58313245Sgabeblack@google.com
58413245Sgabeblack@google.com        printVal(os, str);
58513245Sgabeblack@google.com    }
58613245Sgabeblack@google.com};
58713245Sgabeblack@google.comvoid
58813245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_core::sc_time *v, const std::string &name)
58913245Sgabeblack@google.com{
59013245Sgabeblack@google.com    addNewTraceVal<VcdTraceValTime>(v, name);
59113245Sgabeblack@google.com}
59213245Sgabeblack@google.com
59313245Sgabeblack@google.comtemplate <typename T>
59413245Sgabeblack@google.comclass VcdTraceValInt : public VcdTraceVal<T>
59513245Sgabeblack@google.com{
59613245Sgabeblack@google.com  public:
59713245Sgabeblack@google.com    using VcdTraceVal<T>::VcdTraceVal;
59813245Sgabeblack@google.com
59913245Sgabeblack@google.com    void
60013245Sgabeblack@google.com    output(std::ostream &os) override
60113245Sgabeblack@google.com    {
60213245Sgabeblack@google.com        const int w = this->width();
60313245Sgabeblack@google.com        char str[w + 1];
60413245Sgabeblack@google.com        str[w] = '\0';
60513245Sgabeblack@google.com
60613245Sgabeblack@google.com        const uint64_t val =
60713245Sgabeblack@google.com            static_cast<uint64_t>(this->value()) & ::mask(sizeof(T) * 8);
60813245Sgabeblack@google.com
60913245Sgabeblack@google.com        if (::mask(w) < val) {
61013245Sgabeblack@google.com            for (int i = 0; i < w; i++)
61113245Sgabeblack@google.com                str[i] = 'x';
61213245Sgabeblack@google.com        } else {
61313245Sgabeblack@google.com            for (int i = 0; i < w; i++)
61413245Sgabeblack@google.com                str[i] = ::bits(val, w - i - 1) ? '1' : '0';
61513245Sgabeblack@google.com        }
61613245Sgabeblack@google.com
61713245Sgabeblack@google.com        this->printVal(os, str);
61813245Sgabeblack@google.com    }
61913245Sgabeblack@google.com};
62013245Sgabeblack@google.com
62113245Sgabeblack@google.comvoid
62213245Sgabeblack@google.comVcdTraceFile::addTraceVal(const unsigned char *v, const std::string &name,
62313245Sgabeblack@google.com                          int width)
62413245Sgabeblack@google.com{
62513245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<unsigned char>>(v, name, width);
62613245Sgabeblack@google.com}
62713245Sgabeblack@google.comvoid
62813245Sgabeblack@google.comVcdTraceFile::addTraceVal(const char *v, const std::string &name, int width)
62913245Sgabeblack@google.com{
63013245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<char>>(v, name, width);
63113245Sgabeblack@google.com}
63213245Sgabeblack@google.comvoid
63313245Sgabeblack@google.comVcdTraceFile::addTraceVal(const unsigned short *v, const std::string &name,
63413245Sgabeblack@google.com                          int width)
63513245Sgabeblack@google.com{
63613245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<unsigned short>>(v, name, width);
63713245Sgabeblack@google.com}
63813245Sgabeblack@google.comvoid
63913245Sgabeblack@google.comVcdTraceFile::addTraceVal(const short *v, const std::string &name, int width)
64013245Sgabeblack@google.com{
64113245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<short>>(v, name, width);
64213245Sgabeblack@google.com}
64313245Sgabeblack@google.comvoid
64413245Sgabeblack@google.comVcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
64513245Sgabeblack@google.com                          int width)
64613245Sgabeblack@google.com{
64713245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, width);
64813245Sgabeblack@google.com}
64913245Sgabeblack@google.comvoid
65013245Sgabeblack@google.comVcdTraceFile::addTraceVal(const int *v, const std::string &name, int width)
65113245Sgabeblack@google.com{
65213245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<int>>(v, name, width);
65313245Sgabeblack@google.com}
65413245Sgabeblack@google.comvoid
65513245Sgabeblack@google.comVcdTraceFile::addTraceVal(const unsigned long *v, const std::string &name,
65613245Sgabeblack@google.com                          int width)
65713245Sgabeblack@google.com{
65813245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<unsigned long>>(v, name, width);
65913245Sgabeblack@google.com}
66013245Sgabeblack@google.comvoid
66113245Sgabeblack@google.comVcdTraceFile::addTraceVal(const long *v, const std::string &name, int width)
66213245Sgabeblack@google.com{
66313245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<long>>(v, name, width);
66413245Sgabeblack@google.com}
66513245Sgabeblack@google.com
66613245Sgabeblack@google.comvoid
66713245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::int64 *v, const std::string &name,
66813245Sgabeblack@google.com                          int width)
66913245Sgabeblack@google.com{
67013245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<sc_dt::int64>>(v, name, width);
67113245Sgabeblack@google.com}
67213245Sgabeblack@google.comvoid
67313245Sgabeblack@google.comVcdTraceFile::addTraceVal(const sc_dt::uint64 *v, const std::string &name,
67413245Sgabeblack@google.com                          int width)
67513245Sgabeblack@google.com{
67613245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<sc_dt::uint64>>(v, name, width);
67713245Sgabeblack@google.com}
67813245Sgabeblack@google.com
67913245Sgabeblack@google.comvoid
68013245Sgabeblack@google.comVcdTraceFile::addTraceVal(const unsigned int *v, const std::string &name,
68113245Sgabeblack@google.com                          const char **literals)
68213245Sgabeblack@google.com{
68313245Sgabeblack@google.com    uint64_t count = 0;
68413245Sgabeblack@google.com    while (*literals++)
68513245Sgabeblack@google.com        count++;
68613245Sgabeblack@google.com
68713245Sgabeblack@google.com    int bits = 0;
68813245Sgabeblack@google.com    while (count >> bits)
68913245Sgabeblack@google.com        bits++;
69013245Sgabeblack@google.com
69113245Sgabeblack@google.com    addNewTraceVal<VcdTraceValInt<unsigned int>>(v, name, bits);
69213245Sgabeblack@google.com}
69313245Sgabeblack@google.com
69413245Sgabeblack@google.comvoid
69513245Sgabeblack@google.comVcdTraceFile::writeComment(const std::string &comment)
69613245Sgabeblack@google.com{
69713245Sgabeblack@google.com    stream() << "$comment" << std::endl;
69813245Sgabeblack@google.com    stream() << comment << std::endl;
69913245Sgabeblack@google.com    stream() << "$end" << std::endl << std::endl;
70013245Sgabeblack@google.com}
70113245Sgabeblack@google.com
70213245Sgabeblack@google.com} // namespace sc_gem5
703