Have a go at generating FASM from Torc XDL

This commit is contained in:
Eddie Hung 2018-12-06 14:51:24 -08:00
parent 5f75a8447f
commit 557011cfe6
3 changed files with 120 additions and 29 deletions

View File

@ -56,6 +56,7 @@ po::options_description Xc7CommandHandler::getArchOptions()
specific.add_options()("package", po::value<std::string>(), "set device package");
specific.add_options()("pcf", po::value<std::string>(), "PCF constraints file to ingest");
specific.add_options()("xdl", po::value<std::string>(), "XDL file to write");
specific.add_options()("fasm", po::value<std::string>(), "FASM file to write");
// specific.add_options()("tmfuzz", "run path delay estimate fuzzer");
return specific;
}
@ -83,6 +84,11 @@ void Xc7CommandHandler::customBitstream(Context *ctx)
std::ofstream f(filename);
write_xdl(ctx, f);
}
if (vm.count("fasm")) {
std::string filename = vm["fasm"].as<std::string>();
std::ofstream f(filename);
write_fasm(ctx, f);
}
}
void Xc7CommandHandler::setupArchContext(Context *ctx)

View File

@ -25,6 +25,7 @@
#include "log.h"
#include "nextpnr.h"
#include "util.h"
#include <boost/range/adaptor/reversed.hpp>
#include "torc/Physical.hpp"
using namespace torc::architecture::xilinx;
@ -32,9 +33,8 @@ using namespace torc::physical;
NEXTPNR_NAMESPACE_BEGIN
void write_xdl(const Context *ctx, std::ostream &out)
DesignSharedPtr create_torc_design(const Context *ctx)
{
XdlExporter exporter(out);
auto designPtr = Factory::newDesignPtr("name", torc_info->ddb->getDeviceName(), ctx->args.package, "-1", "");
std::unordered_map<int32_t, InstanceSharedPtr> site_to_instance;
@ -232,6 +232,7 @@ void write_xdl(const Context *ctx, std::ostream &out)
auto pinPtr = Factory::newInstancePinPtr(instPtr, pin_name);
netPtr->addSource(pinPtr);
if (!net.second->users.empty()) {
for (const auto &user : net.second->users) {
site_index = torc_info->bel_to_site_index[user.cell->bel.index];
instPtr = site_to_instance.at(site_index);
@ -264,8 +265,91 @@ void write_xdl(const Context *ctx, std::ostream &out)
netPtr->addPip(p);
}
}
}
return designPtr;
}
void write_xdl(const Context *ctx, std::ostream &out)
{
XdlExporter exporter(out);
auto designPtr = create_torc_design(ctx);
exporter(designPtr);
}
void write_fasm(const Context *ctx, std::ostream &out)
{
auto designPtr = create_torc_design(ctx);
static const boost::regex re_loc(".+_X(\\d+)Y(\\d+)");
boost::smatch what;
// export the instances
Circuit::InstanceSharedPtrConstIterator pi = designPtr->instancesBegin();
Circuit::InstanceSharedPtrConstIterator ei = designPtr->instancesEnd();
for (; pi < ei; ++pi) {
std::stringstream ss;
ss << (*pi)->getTile() << '.';
const auto& type = (*pi)->getType();
if (type == "SLICEL") {
const auto& site_name = (*pi)->getSite();
if (!boost::regex_match(site_name, what, re_loc))
throw;
const auto x = boost::lexical_cast<int>(what.str(1));
ss << type << "_X" << static_cast<int>(x & 1) << '.';
out << "# " << (*pi)->getName() << std::endl;
auto pc = (*pi)->configBegin();
auto ec = (*pi)->configEnd();
for (; pc != ec; ++pc)
if (pc->first == "A6LUT" || pc->first == "B6LUT" || pc->first == "C6LUT" || pc->first == "D6LUT") {
auto name = pc->second.getName();
boost::replace_all(name, "\\:", ":");
auto it = ctx->cells.find(ctx->id(name));
if (it == ctx->cells.end()) it = ctx->cells.find(ctx->id(name + "_LC"));
assert(it != ctx->cells.end());
auto cell = it->second.get();
const auto &init = cell->params[ctx->id("INIT")];
if (cell->lcInfo.inputCount <= 5) {
auto num_bits = (1 << cell->lcInfo.inputCount);
auto init_as_uint = boost::lexical_cast<uint32_t>(init);
out << ss.str() << pc->first[0] << pc->first.substr(2,std::string::npos) << ".INIT";
out << "[" << num_bits-1 << ":0]" << "=";
out << num_bits << "'b";
for (auto i = 0; i < num_bits; ++i)
out << ((init_as_uint >> i) & 1 ? '1' : '0');
out << std::endl;
}
else {
out << ss.str() << pc->first[0] << pc->first.substr(2,std::string::npos) << ".INIT[31:0]=";
out << "32'b" << boost::adaptors::reverse(init.substr(0,32)) << std::endl;
out << ss.str() << pc->first[0] << pc->first.substr(2,std::string::npos) << ".INIT[63:32]=";
out << "32'b" << boost::adaptors::reverse(init.substr(32,32)) << std::endl;
}
}
else
out << ss.str() << pc->first << '.' << pc->second.getValue() << std::endl;
out << std::endl;
}
}
// export the nets
Circuit::NetSharedPtrConstIterator pn = designPtr->netsBegin();
Circuit::NetSharedPtrConstIterator en = designPtr->netsEnd();
for (; pn < en; ++pn) {
out << "# " << (*pn)->getName() << std::endl;
auto pp = (*pn)->pipsBegin();
auto ep = (*pn)->pipsEnd();
for (; pp != ep; ++pp)
out << pp->getTileName() << "." << pp->getSourceWireName() << "." << pp->getSinkWireName() << std::endl;
out << std::endl;
}
}
NEXTPNR_NAMESPACE_END

View File

@ -27,6 +27,7 @@
NEXTPNR_NAMESPACE_BEGIN
void write_xdl(const Context *ctx, std::ostream &out);
void write_fasm(const Context *ctx, std::ostream &out);
NEXTPNR_NAMESPACE_END