diff options
author | gatecat <gatecat@ds0.me> | 2022-08-04 09:04:02 +0200 |
---|---|---|
committer | gatecat <gatecat@ds0.me> | 2022-09-09 14:48:57 +0200 |
commit | f4230553901de30f07be5906471b219ed255cb6e (patch) | |
tree | 601ada70dbe68cd9b34451840752868700de9612 /generic/viaduct/fabulous/fasm.cc | |
parent | b9b16eaa5358dbdf15368eb145be2c70b72c42a9 (diff) | |
download | nextpnr-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.cc | 191 |
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 ¶m : 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 |