aboutsummaryrefslogtreecommitdiffstats
path: root/generic/viaduct/fabulous/fasm.cc
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2022-08-04 09:04:02 +0200
committergatecat <gatecat@ds0.me>2022-09-09 14:48:57 +0200
commitf4230553901de30f07be5906471b219ed255cb6e (patch)
tree601ada70dbe68cd9b34451840752868700de9612 /generic/viaduct/fabulous/fasm.cc
parentb9b16eaa5358dbdf15368eb145be2c70b72c42a9 (diff)
downloadnextpnr-f4230553901de30f07be5906471b219ed255cb6e.tar.gz
nextpnr-f4230553901de30f07be5906471b219ed255cb6e.tar.bz2
nextpnr-f4230553901de30f07be5906471b219ed255cb6e.zip
fabulous: Add a viaduct uarch
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'generic/viaduct/fabulous/fasm.cc')
-rw-r--r--generic/viaduct/fabulous/fasm.cc191
1 files changed, 191 insertions, 0 deletions
diff --git a/generic/viaduct/fabulous/fasm.cc b/generic/viaduct/fabulous/fasm.cc
new file mode 100644
index 00000000..1405766e
--- /dev/null
+++ b/generic/viaduct/fabulous/fasm.cc
@@ -0,0 +1,191 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2021-22 gatecat <gatecat@ds0.me>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "fasm.h"
+#include "log.h"
+#include "nextpnr.h"
+#include "util.h"
+
+#include <algorithm>
+#include <boost/range/adaptor/reversed.hpp>
+#include <fstream>
+
+#define VIADUCT_CONSTIDS "viaduct/fabulous/constids.inc"
+#include "viaduct_constids.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+namespace {
+struct FabFasmWriter
+{
+ FabFasmWriter(const Context *ctx, const FabricConfig &cfg, const std::string &filename)
+ : ctx(ctx), cfg(cfg), out(filename)
+ {
+ if (!out)
+ log_error("failed to open fasm file '%s' for writing\n", filename.c_str());
+ }
+ std::string format_name(IdStringList name)
+ {
+ std::string result;
+ for (IdString entry : name) {
+ if (!result.empty())
+ result += ".";
+ result += entry.str(ctx);
+ }
+ return result;
+ }
+ void write_pip(PipId pip)
+ {
+ auto &data = ctx->pip_info(pip);
+ if (data.type.in(id_global_clock, id_O2Q))
+ return; // pseudo-pips with no underlying bitstream bits
+ // write pip name but with '.' instead of '/' for separator
+ out << format_name(data.name) << std::endl;
+ }
+ void write_routing(const NetInfo *net)
+ {
+ std::vector<PipId> sorted_pips;
+ for (auto &w : net->wires)
+ if (w.second.pip != PipId())
+ sorted_pips.push_back(w.second.pip);
+ std::sort(sorted_pips.begin(), sorted_pips.end());
+ out << stringf("# routing for net '%s'\n", ctx->nameOf(net)) << std::endl;
+ for (auto pip : sorted_pips)
+ write_pip(pip);
+ out << std::endl;
+ }
+
+ std::string prefix;
+
+ // Write a FASM bitvector; optionally inverting the values in the process
+ void write_vector(const std::string &name, const std::vector<bool> &value, bool invert = false)
+ {
+ out << prefix << name << " = " << int(value.size()) << "'b";
+ for (auto bit : boost::adaptors::reverse(value))
+ out << ((bit ^ invert) ? '1' : '0');
+ out << std::endl;
+ }
+ // Write a FASM bitvector given an integer value
+ void write_int_vector(const std::string &name, uint64_t value, int width, bool invert = false)
+ {
+ std::vector<bool> bits(width, false);
+ for (int i = 0; i < width; i++)
+ bits[i] = (value & (1ULL << i)) != 0;
+ write_vector(name, bits, invert);
+ }
+ // Write an int vector param
+ void write_int_vector_param(const CellInfo *cell, const std::string &name, uint64_t defval, int width,
+ bool invert = false)
+ {
+ uint64_t value = int_or_default(cell->params, ctx->id(name), defval);
+ std::vector<bool> bits(width, false);
+ for (int i = 0; i < width; i++)
+ bits[i] = (value & (1ULL << i)) != 0;
+ write_vector(stringf("%s[%d:0]", name.c_str(), width - 1), bits, invert);
+ }
+
+ void write_bool(const CellInfo *cell, const std::string &name)
+ {
+ if (bool_or_default(cell->params, ctx->id(name))) {
+ out << prefix << name << std::endl;
+ }
+ }
+
+ void write_logic(const CellInfo *lc)
+ {
+ prefix = format_name(ctx->getBelName(lc->bel)) + ".";
+ if (lc->type.in(id_FABULOUS_LC, id_FABULOUS_COMB)) {
+ write_int_vector_param(lc, "INIT", 0U, 1U << cfg.clb.lut_k); // todo lut depermute and thru
+ }
+ if (lc->type == id_FABULOUS_LC) {
+ write_bool(lc, "FF");
+ }
+ if (lc->type.in(id_FABULOUS_LC, id_FABULOUS_FF)) {
+ write_bool(lc, "SET_NORESET");
+ write_bool(lc, "NEG_CLK");
+ write_bool(lc, "NEG_EN");
+ write_bool(lc, "NEG_SR");
+ write_bool(lc, "ASYNC_SR");
+ }
+ }
+
+ void write_io(const CellInfo *io)
+ {
+ write_bool(io, "INPUT_USED");
+ write_bool(io, "OUTPUT_USED");
+ write_bool(io, "ENABLE_USED");
+ }
+
+ void write_generic_cell(const CellInfo *ci)
+ {
+ prefix = format_name(ctx->getBelName(ci->bel)) + ".";
+ for (auto &param : ci->params) {
+ // TODO: better parameter type auto-detection
+ if (param.second.is_string) {
+ // enum type parameter
+ out << prefix << param.first.c_str(ctx) << "." << param.second.str << std::endl;
+ } else if (param.second.str.size() == 1) {
+ // boolean type parameter
+ if (param.second.intval != 0)
+ out << prefix << param.first.c_str(ctx) << std::endl;
+ } else {
+ // vector type parameter
+ int msb = int(param.second.str.size()) - 1;
+ out << prefix << param.first.c_str(ctx) << "[" << msb << ":0] = ";
+ for (auto bit : boost::adaptors::reverse(param.second.str))
+ out << bit;
+ out << std::endl;
+ }
+ }
+ }
+
+ void write_cell(const CellInfo *ci)
+ {
+ out << stringf("# config for cell '%s'\n", ctx->nameOf(ci)) << std::endl;
+ if (ci->type.in(id_FABULOUS_COMB, id_FABULOUS_FF, id_FABULOUS_LC))
+ write_logic(ci);
+ else if (ci->type == id_IO_1_bidirectional_frame_config_pass)
+ write_io(ci);
+ else
+ write_generic_cell(ci);
+ // TODO: other cell types
+ out << std::endl;
+ }
+
+ void write_fasm()
+ {
+ for (const auto &net : ctx->nets)
+ write_routing(net.second.get());
+ for (const auto &cell : ctx->cells)
+ write_cell(cell.second.get());
+ }
+
+ const Context *ctx;
+ const FabricConfig &cfg;
+ std::ofstream out;
+};
+} // namespace
+
+void fabulous_write_fasm(const Context *ctx, const FabricConfig &cfg, const std::string &filename)
+{
+ FabFasmWriter wr(ctx, cfg, filename);
+ wr.write_fasm();
+}
+
+NEXTPNR_NAMESPACE_END