Files
fluxengine/lib/fluxsink/vcdfluxsink.cc
dg 18d90c44dd Rework the flux decoders to add a desync opcode for separating multiple reads
in a flux stream. Finally add a unit test for the flux decoder.
2021-12-05 14:42:57 +00:00

83 lines
1.8 KiB
C++

#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "sql.h"
#include "bytes.h"
#include "protocol.h"
#include "fluxsink/fluxsink.h"
#include "decoders/fluxmapreader.h"
#include "lib/fluxsink/fluxsink.pb.h"
#include "proto.h"
#include "fmt/format.h"
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
class VcdFluxSink : public FluxSink
{
public:
VcdFluxSink(const VcdFluxSinkProto& config):
_config(config)
{}
public:
void writeFlux(int cylinder, int head, Fluxmap& fluxmap)
{
mkdir(_config.directory().c_str(), 0744);
std::ofstream of(
fmt::format("{}/c{:02d}.h{:01d}.vcd", _config.directory(), cylinder, head),
std::ios::out | std::ios::binary);
if (!of.is_open())
Error() << "cannot open output file";
of << "$timescale 1ns $end\n"
<< "$var wire 1 i index $end\n"
<< "$var wire 1 p pulse $end\n"
<< "$upscope $end\n"
<< "$enddefinitions $end\n"
<< "$dumpvars 0i 0p $end\n";
FluxmapReader fmr(fluxmap);
unsigned timestamp = 0;
unsigned lasttimestamp = 0;
while (!fmr.eof())
{
unsigned ticks;
int event;
fmr.getNextEvent(event, ticks);
if (fmr.eof())
break;
unsigned newtimestamp = timestamp + ticks;
if (newtimestamp != lasttimestamp)
{
of << fmt::format("\n#{} 0i 0p\n", (uint64_t)((lasttimestamp+1) * NS_PER_TICK));
timestamp = newtimestamp;
of << fmt::format("#{} ", (uint64_t)(timestamp * NS_PER_TICK));
}
if (event & F_BIT_PULSE)
of << "1p ";
if (event & F_BIT_INDEX)
of << "1i ";
lasttimestamp = timestamp;
}
of << "\n";
}
operator std::string () const
{
return fmt::format("vcd({})", _config.directory());
}
private:
const VcdFluxSinkProto& _config;
};
std::unique_ptr<FluxSink> FluxSink::createVcdFluxSink(const VcdFluxSinkProto& config)
{
return std::unique_ptr<FluxSink>(new VcdFluxSink(config));
}