ecp5: Adding bitstream gen for pips and LUT init
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
de82ecad59
commit
bad926bcc3
@ -124,11 +124,11 @@ std::string Arch::getChipName()
|
||||
{
|
||||
|
||||
if (args.type == ArchArgs::LFE5U_25F) {
|
||||
return "Lattice LFE5U-25F";
|
||||
return "LFE5U-25F";
|
||||
} else if (args.type == ArchArgs::LFE5U_45F) {
|
||||
return "Lattice LFE5U-45F";
|
||||
return "LFE5U-45F";
|
||||
} else if (args.type == ArchArgs::LFE5U_85F) {
|
||||
return "Lattice LFE5U-85F";
|
||||
return "LFE5U-85F";
|
||||
} else {
|
||||
log_error("Unknown chip\n");
|
||||
}
|
||||
|
@ -704,6 +704,8 @@ struct Arch : BaseCtx
|
||||
return chip_info->tiletype_names[locInfo(pip)->pip_data[pip.index].tile_type].get();
|
||||
}
|
||||
|
||||
int8_t getPipType(PipId pip) const { return locInfo(pip)->pip_data[pip.index].pip_type; }
|
||||
|
||||
BelId getPackagePinBel(const std::string &pin) const;
|
||||
std::string getBelPackagePin(BelId bel) const;
|
||||
|
||||
|
135
ecp5/bitstream.cc
Normal file
135
ecp5/bitstream.cc
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
|
||||
*
|
||||
* 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 "bitstream.h"
|
||||
|
||||
// From Project Trellis
|
||||
#include "BitDatabase.hpp"
|
||||
#include "Bitstream.hpp"
|
||||
#include "Chip.hpp"
|
||||
#include "ChipConfig.hpp"
|
||||
#include "Tile.hpp"
|
||||
#include "TileConfig.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// Convert an absolute wire name to a relative Trellis one
|
||||
static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire)
|
||||
{
|
||||
std::string basename = ctx->locInfo(wire)->wire_data[wire.index].name.get();
|
||||
std::string prefix2 = basename.substr(0, 2);
|
||||
if (prefix2 == "G_" || prefix2 == "L_" || prefix2 == "R_")
|
||||
return basename;
|
||||
if (loc == wire.location)
|
||||
return basename;
|
||||
std::string rel_prefix;
|
||||
if (wire.location.y < loc.y)
|
||||
rel_prefix += "N" + to_string(loc.y - wire.location.y);
|
||||
if (wire.location.y > loc.y)
|
||||
rel_prefix += "S" + to_string(wire.location.y - loc.y);
|
||||
if (wire.location.x > loc.x)
|
||||
rel_prefix += "E" + to_string(wire.location.x - loc.x);
|
||||
if (wire.location.x < loc.x)
|
||||
rel_prefix += "W" + to_string(loc.x - wire.location.x);
|
||||
return rel_prefix + "_" + basename;
|
||||
}
|
||||
|
||||
static std::vector<bool> int_to_bitvector(int val, int size)
|
||||
{
|
||||
std::vector<bool> bv;
|
||||
for (int i = 0; i < size; i++) {
|
||||
bv.push_back((val & (1 << i)) != 0);
|
||||
}
|
||||
return bv;
|
||||
}
|
||||
|
||||
void write_bitstream(Context *ctx, std::string base_config_file, std::string text_config_file,
|
||||
std::string bitstream_file)
|
||||
{
|
||||
Trellis::Chip empty_chip(ctx->getChipName());
|
||||
Trellis::ChipConfig cc;
|
||||
if (!base_config_file.empty()) {
|
||||
std::ifstream config_file(base_config_file);
|
||||
if (!config_file) {
|
||||
log_error("failed to open base config file '%s'\n", base_config_file.c_str());
|
||||
}
|
||||
std::string str((std::istreambuf_iterator<char>(config_file)), std::istreambuf_iterator<char>());
|
||||
cc = Trellis::ChipConfig::from_string(str);
|
||||
} else {
|
||||
cc.chip_name = ctx->getChipName();
|
||||
// TODO: .bit metadata
|
||||
}
|
||||
|
||||
// Add all set, configurable pips to the config
|
||||
for (auto pip : ctx->getPips()) {
|
||||
if (ctx->getBoundPipNet(pip) != IdString()) {
|
||||
if (ctx->getPipType(pip) == 0) { // ignore fixed pips
|
||||
auto tile = empty_chip.get_tile_by_position_and_type(pip.location.y, pip.location.x,
|
||||
ctx->getPipTiletype(pip));
|
||||
std::string source = get_trellis_wirename(ctx, pip.location, ctx->getPipSrcWire(pip));
|
||||
std::string sink = get_trellis_wirename(ctx, pip.location, ctx->getPipDstWire(pip));
|
||||
cc.tiles[tile->info.name].add_arc(sink, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set all bankref tiles to 3.3V (TODO)
|
||||
for (const auto &tile : empty_chip.tiles) {
|
||||
std::string type = tile.second->info.type;
|
||||
if (type.find("BANKREF") != std::string::npos && type != "BANKREF8") {
|
||||
cc.tiles[type].add_enum("BANK.VCCIO", "3V3");
|
||||
}
|
||||
}
|
||||
|
||||
// Configure slices
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->bel == BelId()) {
|
||||
log_warning("found unplaced cell '%s' during bitstream gen\n", ci->name.c_str(ctx));
|
||||
}
|
||||
BelId bel = ci->bel;
|
||||
if (ci->type == ctx->id("TRELLIS_SLICE")) {
|
||||
auto tile = empty_chip.get_tile_by_position_and_type(bel.location.y, bel.location.x, "PLC2");
|
||||
std::string tname = tile->info.name;
|
||||
std::string slice = ctx->locInfo(bel)->bel_data[bel.index].name.get();
|
||||
int lut0_init = int_or_default(ci->params, ctx->id("LUT0_INITVAL"));
|
||||
int lut1_init = int_or_default(ci->params, ctx->id("LUT1_INITVAL"));
|
||||
cc.tiles[tname].add_word(slice + ".K0.INIT", int_to_bitvector(lut0_init, 16));
|
||||
cc.tiles[tname].add_word(slice + ".K1.INIT", int_to_bitvector(lut1_init, 16));
|
||||
}
|
||||
}
|
||||
|
||||
// Configure chip
|
||||
Trellis::Chip cfg_chip = cc.to_chip();
|
||||
if (!bitstream_file.empty()) {
|
||||
Trellis::Bitstream::serialise_chip(cfg_chip).write_bit_py(bitstream_file);
|
||||
}
|
||||
if (!text_config_file.empty()) {
|
||||
std::ofstream out_config(text_config_file);
|
||||
out_config << cc.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
32
ecp5/bitstream.h
Normal file
32
ecp5/bitstream.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BITSTREAM_H
|
||||
#define BITSTREAM_H
|
||||
|
||||
#include "nextpnr.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
void write_bitstream(Context *ctx, std::string base_config_file = "", std::string text_config_file = "",
|
||||
std::string bitstream_file = "");
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif // BITSTREAM_H
|
30
ecp5/main.cc
30
ecp5/main.cc
@ -32,14 +32,15 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Database.hpp"
|
||||
#include "Chip.hpp"
|
||||
#include "Database.hpp"
|
||||
#include "Tile.hpp"
|
||||
|
||||
#include "log.h"
|
||||
#include "nextpnr.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "design_utils.h"
|
||||
#include "jsonparse.h"
|
||||
#include "pack.h"
|
||||
@ -68,6 +69,10 @@ int main(int argc, char *argv[])
|
||||
options.add_options()("json", po::value<std::string>(), "JSON design file to ingest");
|
||||
options.add_options()("seed", po::value<int>(), "seed value for random number generator");
|
||||
|
||||
options.add_options()("basecfg", po::value<std::string>(), "base chip configuration in Trellis text format");
|
||||
options.add_options()("bit", po::value<std::string>(), "bitstream file to write");
|
||||
options.add_options()("textcfg", po::value<std::string>(), "textual configuration in Trellis format to write");
|
||||
|
||||
po::positional_options_description pos;
|
||||
#ifndef NO_PYTHON
|
||||
options.add_options()("run", po::value<std::vector<std::string>>(), "python file to execute");
|
||||
@ -148,17 +153,18 @@ int main(int argc, char *argv[])
|
||||
if (!route_design(&ctx) && !ctx.force)
|
||||
log_error("Routing design failed.\n");
|
||||
|
||||
// TEST BEGIN
|
||||
Trellis::Chip c("LFE5U-45F");
|
||||
for (auto pip : ctx.getPips()) {
|
||||
if (!ctx.checkPipAvail(pip)) {
|
||||
auto tile = c.get_tile_by_position_and_type(pip.location.y, pip.location.x, ctx.getPipTiletype(pip));
|
||||
std::cout << ctx.getWireName(ctx.getPipSrcWire(pip)).str(&ctx) << " -> "
|
||||
<< ctx.getWireName(ctx.getPipDstWire(pip)).str(&ctx) << " [in tile "
|
||||
<< tile->info.name << "]" << std::endl;
|
||||
}
|
||||
}
|
||||
// TEST END
|
||||
std::string basecfg;
|
||||
if (vm.count("basecfg"))
|
||||
basecfg = vm["basecfg"].as<std::string>();
|
||||
|
||||
std::string bitstream;
|
||||
if (vm.count("bit"))
|
||||
bitstream = vm["bit"].as<std::string>();
|
||||
|
||||
std::string textcfg;
|
||||
if (vm.count("textcfg"))
|
||||
textcfg = vm["textcfg"].as<std::string>();
|
||||
write_bitstream(&ctx, basecfg, textcfg, bitstream);
|
||||
}
|
||||
|
||||
#ifndef NO_PYTHON
|
||||
|
2
ecp5/synth/.gitignore
vendored
2
ecp5/synth/.gitignore
vendored
@ -0,0 +1,2 @@
|
||||
*.config
|
||||
*.bit
|
Loading…
Reference in New Issue
Block a user