diff options
| author | 2019-01-19 23:37:01 +0100 | |
|---|---|---|
| committer | 2019-01-20 18:29:27 +0100 | |
| commit | 83d558d0962efbb20cfa8e3589b9377e10818e1c (patch) | |
| tree | f2349f270cf2e74bfcc641262174d9760b1dcd8d /src/lib | |
| parent | 95cd81e5fddc0a8c4f5d7e27cd7c2e7188d9fbfc (diff) | |
netlist: nlwav now also converts log files to VCD format. [couriersud]
Please refer to nlwav --help for examples. There is also an example how
to create multi-channel wav files.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/netlist/nl_base.h | 4 | ||||
| -rw-r--r-- | src/lib/netlist/plib/poptions.cpp | 74 | ||||
| -rw-r--r-- | src/lib/netlist/plib/poptions.h | 11 | ||||
| -rw-r--r-- | src/lib/netlist/plib/pstream.h | 4 | ||||
| -rw-r--r-- | src/lib/netlist/prg/nlwav.cpp | 501 |
5 files changed, 393 insertions, 201 deletions
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index f09715bbbc4..97f83735028 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -1064,7 +1064,7 @@ namespace netlist protected: virtual void changed() override { - stream()->read(&m_data[0],1<<AW); + stream()->read(reinterpret_cast<plib::pistream::value_type *>(&m_data[0]),1<<AW); } private: @@ -1490,7 +1490,7 @@ namespace netlist { auto f = stream(); if (f != nullptr) - f->read(&m_data[0],1<<AW); + f->read(reinterpret_cast<plib::pistream::value_type *>(&m_data[0]),1<<AW); else device.state().log().warning("Rom {1} not found", Value()); } diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp index de00f9efa4a..43e992f9225 100644 --- a/src/lib/netlist/plib/poptions.cpp +++ b/src/lib/netlist/plib/poptions.cpp @@ -7,6 +7,7 @@ #include "poptions.h" #include "ptypes.h" +#include "pexception.h" namespace plib { /*************************************************************************** @@ -62,15 +63,17 @@ namespace plib { } options::options() + : m_other_args(nullptr) { } options::options(option *o[]) + : m_other_args(nullptr) { int i=0; while (o[i] != nullptr) { - m_opts.push_back(o[i]); + register_option(o[i]); i++; } } @@ -85,9 +88,39 @@ namespace plib { m_opts.push_back(opt); } + void options::check_consistency() + { + for (auto &opt : m_opts) + { + option *o = dynamic_cast<option *>(opt); + if (o != nullptr) + { + if (o->short_opt() == "" && o->long_opt() == "") + { + option_args *ov = dynamic_cast<option_args *>(o); + if (ov != nullptr) + { + if (m_other_args != nullptr) + { + throw pexception("other args can only be specified once!"); + } + else + { + m_other_args = ov; + } + } + else + throw pexception("found option with neither short or long tag!" ); + } + } + } + } + int options::parse(int argc, char *argv[]) { + check_consistency(); m_app = pstring(argv[0]); + bool seen_other_args = false; for (int i=1; i<argc; ) { @@ -96,19 +129,27 @@ namespace plib { pstring opt_arg; bool has_equal_arg = false; - if (plib::startsWith(arg, "--")) + if (!seen_other_args && plib::startsWith(arg, "--")) { auto v = psplit(arg.substr(2),"="); - opt = getopt_long(v[0]); - has_equal_arg = (v.size() > 1); - if (has_equal_arg) + if (v.size() && v[0] != pstring("")) { - for (unsigned j = 1; j < v.size() - 1; j++) - opt_arg = opt_arg + v[j] + "="; - opt_arg += v[v.size()-1]; + opt = getopt_long(v[0]); + has_equal_arg = (v.size() > 1); + if (has_equal_arg) + { + for (unsigned j = 1; j < v.size() - 1; j++) + opt_arg = opt_arg + v[j] + "="; + opt_arg += v[v.size()-1]; + } + } + else + { + opt = m_other_args; + seen_other_args = true; } } - else if (plib::startsWith(arg, "-")) + else if (!seen_other_args && plib::startsWith(arg, "-")) { std::size_t p = 1; opt = getopt_short(arg.substr(p, 1)); @@ -121,7 +162,11 @@ namespace plib { } else { - return i; + seen_other_args = true; + if (m_other_args == nullptr) + return i; + opt = m_other_args; + i--; // we haven't had an option specifier; } if (opt == nullptr) return i; @@ -183,6 +228,10 @@ namespace plib { for (auto & optbase : m_opts ) { + // Skip anonymous inputs which are collected in option_args + if (dynamic_cast<option_args *>(optbase) != nullptr) + continue; + if (auto opt = dynamic_cast<option *>(optbase)) { pstring line = ""; @@ -227,6 +276,7 @@ namespace plib { if (grp->help() != "") ret += split_paragraphs(grp->help(), width, 4, 4) + "\n"; } } + // FIXME: other help ... pstring ex(""); for (auto & optbase : m_opts ) { @@ -248,7 +298,7 @@ namespace plib { for (auto & optbase : m_opts) { auto opt = dynamic_cast<option *>(optbase); - if (opt && opt->short_opt() == arg) + if (opt && arg != "" && opt->short_opt() == arg) return opt; } return nullptr; @@ -258,7 +308,7 @@ namespace plib { for (auto & optbase : m_opts) { auto opt = dynamic_cast<option *>(optbase); - if (opt && opt->long_opt() == arg) + if (opt && arg !="" && opt->long_opt() == arg) return opt; } return nullptr; diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h index f3be4b061dd..4a8e6d788d7 100644 --- a/src/lib/netlist/plib/poptions.h +++ b/src/lib/netlist/plib/poptions.h @@ -212,6 +212,14 @@ private: std::vector<pstring> m_val; }; +class option_args : public option_vec +{ +public: + option_args(options &parent, pstring help) + : option_vec(parent, "", "", help) + {} +}; + class options { public: @@ -233,6 +241,8 @@ private: static pstring split_paragraphs(pstring text, unsigned width, unsigned indent, unsigned firstline_indent); + void check_consistency(); + template <typename T> T *getopt_type() { @@ -249,6 +259,7 @@ private: std::vector<option_base *> m_opts; pstring m_app; + option_args * m_other_args; }; } diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h index cc86a1a39ea..ad461bb3e20 100644 --- a/src/lib/netlist/plib/pstream.h +++ b/src/lib/netlist/plib/pstream.h @@ -120,7 +120,7 @@ protected: virtual size_type vread(T *buf, const size_type n) = 0; }; -typedef pistream_base<std::uint8_t> pistream; +typedef pistream_base<char> pistream; // ----------------------------------------------------------------------------- // postream: output stream @@ -150,7 +150,7 @@ protected: private: }; -typedef postream_base<std::uint8_t> postream; +typedef postream_base<char> postream; // ----------------------------------------------------------------------------- // pomemstream: output string stream diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp index 361b1db5195..badf31594ac 100644 --- a/src/lib/netlist/prg/nlwav.cpp +++ b/src/lib/netlist/prg/nlwav.cpp @@ -8,37 +8,6 @@ #include "../plib/ppmf.h" #include "../nl_setup.h" -class nlwav_app : public plib::app -{ -public: - nlwav_app() : - plib::app(), - opt_inp(*this, "i", "input", "-", "input file"), - opt_out(*this, "o", "output", "-", "output file"), - opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction"), - opt_rate(*this, "r", "rate", 48000, "sample rate of output file"), - opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"), - opt_quiet(*this,"q", "quiet", "be quiet - no warnings"), - opt_version(*this, "", "version", "display version and exit"), - opt_help(*this, "h", "help", "display help and exit") - {} - plib::option_str opt_inp; - plib::option_str opt_out; - plib::option_num<double> opt_amp; - plib::option_num<long> opt_rate; - plib::option_bool opt_verb; - plib::option_bool opt_quiet; - plib::option_bool opt_version; - plib::option_bool opt_help; - - int execute(); - pstring usage(); - - plib::pstdin pin_strm; -private: - void convert1(long sample_rate); - void convert(long sample_rate); -}; /* From: https://ffmpeg.org/pipermail/ffmpeg-devel/2007-October/038122.html @@ -55,9 +24,10 @@ private: class wav_t { public: - wav_t(plib::postream &strm, unsigned sr) : m_f(strm) + wav_t(plib::postream &strm, std::size_t sr, std::size_t channels) + : m_f(strm) { - initialize(sr); + initialize(sr, channels); write(m_fh); write(m_fmt); write(m_data); @@ -76,8 +46,8 @@ public: } } - unsigned channels() { return m_fmt.channels; } - unsigned sample_rate() { return m_fmt.sample_rate; } + std::size_t channels() { return m_fmt.channels; } + std::size_t sample_rate() { return m_fmt.sample_rate; } template <typename T> void write(const T &val) @@ -85,11 +55,14 @@ public: m_f.write(reinterpret_cast<const plib::postream::value_type *>(&val), sizeof(T)); } - void write_sample(int sample) + void write_sample(int *sample) { m_data.len += m_fmt.block_align; - int16_t ps = static_cast<int16_t>(sample); /* 16 bit sample, FIXME: Endianess? */ - write(ps); + for (std::size_t i = 0; i < channels(); i++) + { + int16_t ps = static_cast<int16_t>(sample[i]); /* 16 bit sample, FIXME: Endianess? */ + write(ps); + } } private: @@ -119,7 +92,7 @@ private: // data follows }; - void initialize(unsigned sr) + void initialize(std::size_t sr, std::size_t channels) { std::memcpy(m_fh.group_id, "RIFF", 4); m_fh.filelen = 0x0; // Fixme @@ -128,8 +101,8 @@ private: std::memcpy(m_fmt.signature, "fmt ", 4); m_fmt.fmt_length = 16; m_fmt.format_tag = 0x0001; //PCM - m_fmt.channels = 1; - m_fmt.sample_rate = sr; + m_fmt.channels = static_cast<std::uint16_t>(channels); + m_fmt.sample_rate = static_cast<std::uint32_t>(sr); m_fmt.bits_sample = 16; m_fmt.block_align = m_fmt.channels * ((m_fmt.bits_sample + 7) / 8); m_fmt.bytes_per_second = m_fmt.sample_rate * m_fmt.block_align; @@ -138,7 +111,6 @@ private: //m_data.len = m_fmt.bytes_per_second * 2 * 0; /* force "play" to play and warn about eof instead of being silent */ m_data.len = (m_f.seekable() ? 0 : 0xffffffff); - } riff_chunk_t m_fh; @@ -146,235 +118,373 @@ private: riff_data_t m_data; plib::postream &m_f; - }; class log_processor { public: - typedef plib::pmfp<void, double, double> callback_type; - log_processor(callback_type cb) : m_cb(cb) { } + typedef plib::pmfp<void, std::size_t, double, double> callback_type; - void process(std::unique_ptr<plib::pistream> &&is) + struct elem { - plib::putf8_reader reader(std::move(is)); + elem() : t(0), v(0), eof(false), need_more(true) { } + double t; + double v; + bool eof; + bool need_more; + }; + + log_processor(std::size_t channels, callback_type &cb) + : m_cb(cb) + , m_e(channels) + { } + + bool readmore(std::vector<plib::putf8_reader> &r) + { + bool success = false; + for (std::size_t i = 0; i< r.size(); i++) + { + if (m_e[i].need_more) + { + pstring line; + m_e[i].eof = !r[i].readline(line); + if (!m_e[i].eof) + { + sscanf(line.c_str(), "%lf %lf", &m_e[i].t, &m_e[i].v); + m_e[i].need_more = false; + } + } + success |= !m_e[i].eof; + } + return success; + } + + void process(std::vector<std::unique_ptr<plib::pistream>> &is) + { + std::vector<plib::putf8_reader> readers; + for (std::size_t i = 0; i < is.size(); i++) + { + plib::putf8_reader r(std::move(is[i])); + readers.push_back(std::move(r)); + } + pstring line; + bool more = readmore(readers); - while(reader.readline(line)) + while (more) { - double t = 0.0; double v = 0.0; - sscanf(line.c_str(), "%lf %lf", &t, &v); - m_cb(t, v); + double mint = 1e200; + std::size_t mini = 0; + for (std::size_t i = 0; i<readers.size(); i++) + if (!m_e[i].need_more) + { + if (m_e[i].t < mint) + { + mint = m_e[i].t; + mini = i; + } + } + + m_e[mini].need_more = true; + m_cb(mini, mint, m_e[mini].v); + more = readmore(readers); } } private: callback_type m_cb; + std::vector<elem> m_e; }; struct aggregator { - typedef plib::pmfp<void, double, double> callback_type; + typedef plib::pmfp<void, std::size_t, double, double> callback_type; - aggregator(double quantum, callback_type cb) - : m_quantum(quantum) + aggregator(std::size_t channels, double quantum, callback_type cb) + : m_channels(channels) + , m_quantum(quantum) , m_cb(cb) , ct(0.0) , lt(0.0) - , outsam(0.0) - , cursam(0.0) + , outsam(channels, 0.0) + , cursam(channels, 0.0) { } - void process(double time, double val) + void process(std::size_t chan, double time, double val) { - while (time >= ct) + while (time >= ct + m_quantum) { - outsam += (ct - lt) * cursam; - outsam = outsam / m_quantum; - m_cb(ct, outsam); - outsam = 0.0; + for (std::size_t i=0; i< m_channels; i++) + { + outsam[i] += (ct - lt) * cursam[i]; + outsam[i] = outsam[i] / m_quantum; + m_cb(i, ct, outsam[i]); + outsam[i] = 0.0; + } lt = ct; ct += m_quantum; } - outsam += (time-lt)*cursam; + for (std::size_t i=0; i< m_channels; i++) + outsam[i] += (time-lt)*cursam[i]; lt = time; - cursam = val; + cursam[chan] = val; } private: + std::size_t m_channels; double m_quantum; callback_type m_cb; double ct; double lt; - double outsam; - double cursam; + std::vector<double> outsam; + std::vector<double> cursam; }; class wavwriter { public: - wavwriter(plib::postream &fo, unsigned sample_rate, double ampa) - : mean(0.0) - , means(0.0) - , maxsam(-1e9) - , minsam(1e9) - , n(0) + wavwriter(plib::postream &fo, std::size_t channels, std::size_t sample_rate, double ampa) + : mean(channels, 0.0) + , means(channels, 0.0) + , maxsam(channels, -1e9) + , minsam(channels, 1e9) + , m_n(channels, 0) + , m_samples(channels, 0) + , m_last_time(0) , m_fo(fo) - , amp(ampa) - , m_wo(m_fo, sample_rate) + , m_amp(ampa) + , m_wo(m_fo, sample_rate, channels) { } - void process(double time, double outsam) + void process(std::size_t chan, double time, double outsam) { - means += outsam; - maxsam = std::max(maxsam, outsam); - minsam = std::min(minsam, outsam); - n++; - //mean = means / (double) n; - mean += 5.0 / static_cast<double>(m_wo.sample_rate()) * (outsam - mean); - - outsam = (outsam - mean) * amp; + if (time > m_last_time) + m_wo.write_sample(m_samples.data()); + m_last_time = time; + means[chan] += outsam; + maxsam[chan] = std::max(maxsam[chan], outsam); + minsam[chan] = std::min(minsam[chan], outsam); + m_n[chan]++; + //mean = means / (double) m_n; + mean[chan] += 5.0 / static_cast<double>(m_wo.sample_rate()) * (outsam - mean[chan]); + + outsam = (outsam - mean[chan]) * m_amp; outsam = std::max(-32000.0, outsam); outsam = std::min(32000.0, outsam); - m_wo.write_sample(static_cast<int>(outsam)); + m_samples[chan] = static_cast<int>(outsam); } - double mean; - double means; - double maxsam; - double minsam; - std::size_t n; + std::vector<double> mean; + std::vector<double> means; + std::vector<double> maxsam; + std::vector<double> minsam; + std::vector<std::size_t> m_n; + std::vector<int> m_samples; + double m_last_time; private: + plib::postream &m_fo; - double amp; + double m_amp; wav_t m_wo; }; -void nlwav_app::convert(long sample_rate) +class vcdwriter { - plib::postream *fo = (opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opt_out())); - std::unique_ptr<plib::pistream> fin = (opt_inp() == "-" ? - plib::make_unique<plib::pstdin>() - : plib::make_unique<plib::pifilestream>(opt_inp())); - plib::putf8_reader reader(std::move(fin)); - wav_t *wo = plib::palloc<wav_t>(*fo, static_cast<unsigned>(sample_rate)); - - double dt = 1.0 / static_cast<double>(wo->sample_rate()); - double ct = dt; - //double mean = 2.4; - double amp = opt_amp(); - double mean = 0.0; - double means = 0.0; - double cursam = 0.0; - double outsam = 0.0; - double lt = 0.0; - double maxsam = -1e9; - double minsam = 1e9; - int n = 0; - //short sample = 0; - pstring line; - - while(reader.readline(line)) +public: + + enum format_e { -#if 1 - double t = 0.0; double v = 0.0; - sscanf(line.c_str(), "%lf %lf", &t, &v); - while (t >= ct) + DIGITAL, + ANALOG + }; + + vcdwriter(plib::postream &fo, std::vector<pstring> channels, + format_e format, double high_level = 2.0, double low_level = 1.0) + : m_channels(channels.size()) + , m_last_time(0) + , m_fo(fo) + , m_high_level(high_level) + , m_low_level(low_level) + , m_format(format) + { + for (pstring::value_type c = 64; c < 64+26; c++) + m_ids.push_back(pstring(c)); + write("$date Sat Jan 19 14:14:17 2019\n"); + write("$end\n"); + write("$version Netlist nlwav 0.1\n"); + write("$end\n"); + write("$timescale 1 ns\n"); + write("$end\n"); + std::size_t i = 0; + for (auto ch : channels) { - outsam += (ct - lt) * cursam; - outsam = outsam / dt; - if (t>0.0) - { - means += outsam; - maxsam = std::max(maxsam, outsam); - minsam = std::min(minsam, outsam); - n++; - //mean = means / (double) n; - mean += 5.0 / static_cast<double>(wo->sample_rate()) * (outsam - mean); - } - outsam = (outsam - mean) * amp; - outsam = std::max(-32000.0, outsam); - outsam = std::min(32000.0, outsam); - wo->write_sample(static_cast<int>(outsam)); - outsam = 0.0; - lt = ct; - ct += dt; + // $var real 64 N1X1 N1X1 $end + if (format == ANALOG) + write(pstring("$var real 64 ") + m_ids[i++] + " " + ch + " $end\n"); + else if (format == DIGITAL) + write(pstring("$var wire 1 ") + m_ids[i++] + " " + ch + " $end\n"); } - outsam += (t-lt)*cursam; - lt = t; - cursam = v; -#else - float t = 0.0; float v = 0.0; - fscanf(FIN, "%f %f", &t, &v); - while (ct <= t) + write("$enddefinitions $end\n"); + if (format == ANALOG) { - wo.write_sample(sample); - n++; - ct += dt; + write("$dumpvars\n"); + //r0.0 N1X1 + for (i = 0; i < channels.size(); i++) + write(pstring("r0.0 ") + m_ids[i] + "\n"); + write("$end\n"); } - means += v; - mean = means / (double) n; - v = v - mean; - v = v * amp; - if (v>32000.0) - v = 32000.0; - else if (v<-32000.0) - v = -32000.0; - sample = v; - //printf("%f %f\n", t, v); -#endif + } - plib::pfree(wo); - if (opt_out() != "-") - plib::pfree(fo); - if (!opt_quiet()) + void process(std::size_t chan, double time, double outsam) + { + if (time > m_last_time) + { + write(pstring("#") + plib::to_string(static_cast<std::int64_t>(m_last_time * 1e9)) + " "); + write(m_buf + "\n"); + m_buf = ""; + m_last_time = time; + } + if (m_format == ANALOG) + m_buf += "r" + plib::to_string(outsam)+ " " + m_ids[chan] + " "; + else + { + if (outsam >= m_high_level) + m_buf += pstring("1") + m_ids[chan] + " "; + else if (outsam <= m_low_level) + m_buf += pstring("0") + m_ids[chan] + " "; + } + } + + std::size_t m_channels; + double m_last_time; + +private: + void write(pstring line) { - perr("Mean (low freq filter): {}\n", mean); - perr("Mean (static): {}\n", means / static_cast<double>(n)); - perr("Amp + {}\n", 32000.0 / (maxsam- mean)); - perr("Amp - {}\n", -32000.0 / (minsam- mean)); + auto p = static_cast<const char *>(line.c_str()); + std::size_t len = std::strlen(p); + m_fo.write(p, len); } -} -void nlwav_app::convert1(long sample_rate) + plib::postream &m_fo; + std::vector<pstring> m_ids; + pstring m_buf; + double m_high_level; + double m_low_level; + format_e m_format; +}; + +class nlwav_app : public plib::app { - plib::postream *fo = (opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opt_out())); - std::unique_ptr<plib::pistream> fin = (opt_inp() == "-" ? - plib::make_unique<plib::pstdin>() - : plib::make_unique<plib::pifilestream>(opt_inp())); +public: + nlwav_app() : + plib::app(), + opt_fmt(*this, "f", "format", 0, std::vector<pstring>({"wav","vcda","vcdd"}), + "output format. Available options are wav|vcda|vcdd.\n" + "wav : multichannel wav output\n" + "vcda : analog VCD output\n" + "vcdd : digital VCD output\n" + "Digital signals are created using the high and low options" + ), + opt_out(*this, "o", "output", "-", "output file"), + opt_rate(*this, "r", "rate", 48000, "sample rate of output file"), + opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction (wav only)"), + opt_high(*this, "u", "high", 2.0, "minimum input for high level (vcdd only)"), + opt_low(*this, "l", "low", 1.0, "maximum input for low level (vcdd only)"), + opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"), + opt_quiet(*this,"q", "quiet", "be quiet - no warnings"), + opt_args(*this, "input file(s)"), + opt_version(*this, "", "version", "display version and exit"), + opt_help(*this, "h", "help", "display help and exit"), + opt_ex1(*this, "./nlwav -f vcdd -o x.vcd log_V*", + "convert all files starting with \"log_V\" into a digital vcd file"), + opt_ex2(*this, "./nlwav -f wav -o x.wav log_V*", + "convert all files starting with \"log_V\" into a multichannel wav file"), + m_outstrm(nullptr) + {} + plib::option_str_limit<unsigned> opt_fmt; + plib::option_str opt_out; + plib::option_num<std::size_t> opt_rate; + plib::option_num<double> opt_amp; + plib::option_num<double> opt_high; + plib::option_num<double> opt_low; + plib::option_bool opt_verb; + plib::option_bool opt_quiet; + plib::option_args opt_args; + plib::option_bool opt_version; + plib::option_bool opt_help; + plib::option_example opt_ex1; + plib::option_example opt_ex2; - double dt = 1.0 / static_cast<double>(sample_rate); + int execute(); + pstring usage(); - wavwriter *wo = plib::palloc<wavwriter>(*fo, static_cast<unsigned>(sample_rate), opt_amp()); - aggregator ag(dt, aggregator::callback_type(&wavwriter::process, wo)); - log_processor lp(log_processor::callback_type(&aggregator::process, &ag)); + plib::pstdin pin_strm; +private: + void convert_wav(); + void convert_vcd(vcdwriter::format_e format); + std::vector<std::unique_ptr<plib::pistream>> m_instrms; + plib::postream *m_outstrm; +}; + +void nlwav_app::convert_wav() +{ - lp.process(std::move(fin)); + double dt = 1.0 / static_cast<double>(opt_rate()); + + std::unique_ptr<wavwriter> wo = plib::make_unique<wavwriter>(*m_outstrm, m_instrms.size(), opt_rate(), opt_amp()); + std::unique_ptr<aggregator> ago = plib::make_unique<aggregator>(m_instrms.size(), dt, aggregator::callback_type(&wavwriter::process, wo.get())); + aggregator::callback_type agcb = log_processor::callback_type(&aggregator::process, ago.get()); + + log_processor lp(m_instrms.size(), agcb); + + lp.process(m_instrms); if (!opt_quiet()) { +#if 0 perr("Mean (low freq filter): {}\n", wo->mean); - perr("Mean (static): {}\n", wo->means / static_cast<double>(wo->n)); + perr("Mean (static): {}\n", wo->means / static_cast<double>(wo->m_n)); perr("Amp + {}\n", 32000.0 / (wo->maxsam - wo->mean)); perr("Amp - {}\n", -32000.0 / (wo->minsam - wo->mean)); +#endif } +} - plib::pfree(wo); - if (opt_out() != "-") - plib::pfree(fo); +void nlwav_app::convert_vcd(vcdwriter::format_e format) +{ + + std::unique_ptr<vcdwriter> wo = plib::make_unique<vcdwriter>(*m_outstrm, opt_args(), + format, opt_high(), opt_low()); + log_processor::callback_type agcb = log_processor::callback_type(&vcdwriter::process, wo.get()); + log_processor lp(m_instrms.size(), agcb); + + lp.process(m_instrms); + + if (!opt_quiet()) + { +#if 0 + perr("Mean (low freq filter): {}\n", wo->mean); + perr("Mean (static): {}\n", wo->means / static_cast<double>(wo->m_n)); + perr("Amp + {}\n", 32000.0 / (wo->maxsam - wo->mean)); + perr("Amp - {}\n", -32000.0 / (wo->minsam - wo->mean)); +#endif + } } pstring nlwav_app::usage() { return help("Convert netlist log files into wav files.\n", - "nltool [options]"); + "nlwav [OPTION] ... [FILE] ..."); } int nlwav_app::execute() { + for (auto &i : opt_args()) + pout(pstring("Hello : ") + i + "\n"); if (opt_help()) { pout(usage()); @@ -393,10 +503,31 @@ int nlwav_app::execute() return 0; } - if ((1)) - convert1(opt_rate()); - else - convert(opt_rate()); + m_outstrm = (opt_out() == "-" ? &pout_strm : plib::palloc<plib::pofilestream>(opt_out())); + + for (auto &oi: opt_args()) + { + std::unique_ptr<plib::pistream> fin = (oi == "-" ? + plib::make_unique<plib::pstdin>() + : plib::make_unique<plib::pifilestream>(oi)); + m_instrms.push_back(std::move(fin)); + } + + switch (opt_fmt()) + { + case 0: + convert_wav(); break; + case 1: + convert_vcd(vcdwriter::ANALOG); break; + case 2: + convert_vcd(vcdwriter::DIGITAL); break; + default: + // tease compiler - can't happen + break; + } + + if (opt_out() != "-") + plib::pfree(m_outstrm); return 0; } |
