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