diff options
-rw-r--r-- | ecp5/bitstream.cc | 57 | ||||
-rw-r--r-- | ecp5/config.cc | 24 | ||||
-rw-r--r-- | ecp5/config.h | 1 |
3 files changed, 82 insertions, 0 deletions
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 3ce2af9b..88d95439 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -20,6 +20,7 @@ #include "bitstream.h" #include <fstream> +#include <iomanip> #include <regex> #include <streambuf> @@ -111,6 +112,43 @@ static void tie_cib_signal(Context *ctx, ChipConfig &cc, WireId wire, bool value NPNR_ASSERT_FALSE("CIB tile not found at location"); } +inline int chtohex(char c) +{ + static const std::string hex = "0123456789ABCDEF"; + return hex.find(c); +} + +std::vector<bool> parse_init_str(const std::string &str, int length) +{ + // Parse a string that may be binary or hex + std::vector<bool> result; + result.resize(length, false); + if (str.substr(0, 2) == "0x") { + // Lattice style hex string + if (int(str.length()) > (2 + ((length + 3) / 4))) + log_error("hex string value too long, expected up to %d chars and found %d.\n", (2 + ((length + 3) / 4)), + int(str.length())); + for (int i = 0; i < int(str.length()) - 2; i++) { + char c = str.at((str.size() - i) - 1); + int nibble = chtohex(c); + result.at(i * 4) = nibble & 0x1; + result.at(i * 4 + 1) = nibble & 0x2; + result.at(i * 4 + 2) = nibble & 0x4; + result.at(i * 4 + 3) = nibble & 0x8; + } + } else { + // Yosys style binary string + if (int(str.length()) > length) + log_error("hex string value too long, expected up to %d bits and found %d.\n", length, int(str.length())); + for (int i = 0; i < int(str.length()); i++) { + char c = str.at((str.size() - i) - 1); + NPNR_ASSERT(c == '0' || c == '1' || c == 'X'); + result.at(i) = (c == '1'); + } + } + return result; +} + // Get the PIO tile corresponding to a PIO bel static std::string get_pio_tile(Context *ctx, BelId bel) { @@ -516,6 +554,25 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex tg.config.add_word(ebr + ".CSDECODE_A", csd_a); tg.config.add_word(ebr + ".CSDECODE_B", csd_b); + std::vector<uint16_t> init_data; + init_data.resize(2048, 0x0); + // INIT_00 .. INIT_3F + for (int i = 0; i <= 0x3F; i++) { + IdString param = ctx->id("INIT_" + + fmt_str(std::hex << std::uppercase << std::setw(2) << std::setfill('0') << i)); + auto value = parse_init_str(str_or_default(ci->params, param, "0"), 320); + for (int j = 0; j < 16; j++) { + // INIT parameter consists of 16 18-bit words with 2-bit padding + int ofs = 20 * j; + for (int k = 0; k < 18; k++) { + if (init_data.at(ofs + k)) + init_data.at(i * 32 + j * 2 + (k / 9)) |= (1 << (k % 9)); + } + } + } + int wid = int_or_default(ci->attrs, ctx->id("WID"), 0); + NPNR_ASSERT(!cc.bram_data.count(wid)); + cc.bram_data[wid] = init_data; cc.tilegroups.push_back(tg); } else { NPNR_ASSERT_FALSE("unsupported cell type"); diff --git a/ecp5/config.cc b/ecp5/config.cc index 2d4f8b1e..c8f94857 100644 --- a/ecp5/config.cc +++ b/ecp5/config.cc @@ -19,6 +19,7 @@ #include "config.h" #include <boost/range/adaptor/reversed.hpp> +#include <iomanip> #include "log.h" NEXTPNR_NAMESPACE_BEGIN @@ -274,6 +275,19 @@ std::ostream &operator<<(std::ostream &out, const ChipConfig &cc) out << std::endl; } } + for (const auto &bram : cc.bram_data) { + out << ".bram_init " << bram.first << std::endl; + std::ios_base::fmtflags f(out.flags()); + for (size_t i = 0; i < bram.second.size(); i++) { + out << std::setw(3) << std::setfill('0') << std::hex << bram.second.at(i); + if (i % 8 == 7) + out << std::endl; + else + out << " "; + } + out.flags(f); + out << std::endl; + } for (const auto &tg : cc.tilegroups) { out << ".tile_group"; for (const auto &tile : tg.tiles) { @@ -316,6 +330,16 @@ std::istream &operator>>(std::istream &in, ChipConfig &cc) } in >> tg.config; cc.tilegroups.push_back(tg); + } else if (verb == ".bram_init") { + uint16_t bram; + in >> bram; + std::ios_base::fmtflags f(in.flags()); + while (!skip_check_eor(in)) { + uint16_t value; + in >> std::hex >> value; + cc.bram_data[bram].push_back(value); + } + in.flags(f); } else { log_error("unrecognised config entry %s\n", verb.c_str()); } diff --git a/ecp5/config.h b/ecp5/config.h index c7e2c3d9..8b38de5d 100644 --- a/ecp5/config.h +++ b/ecp5/config.h @@ -114,6 +114,7 @@ class ChipConfig std::vector<std::string> metadata; std::map<std::string, TileConfig> tiles; std::vector<TileGroup> tilegroups; + std::map<uint16_t, std::vector<uint16_t>> bram_data; }; std::ostream &operator<<(std::ostream &out, const ChipConfig &cc); |