machxo2: Start creating MachXO2CommandHandler.
This commit is contained in:
parent
98214865be
commit
9704f422dc
@ -20,6 +20,7 @@
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include "nextpnr.h"
|
||||
#include "embed.h"
|
||||
#include "placer1.h"
|
||||
#include "placer_heap.h"
|
||||
#include "router1.h"
|
||||
@ -36,7 +37,44 @@ Arch::Arch(ArchArgs args) : chipName("generic"), args(args)
|
||||
decal_graphics[IdString()];
|
||||
}
|
||||
|
||||
void IdString::initialize_arch(const BaseCtx *ctx) {}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void IdString::initialize_arch(const BaseCtx *ctx) {
|
||||
#define X(t) initialize_add(ctx, #t, ID_##t);
|
||||
|
||||
#include "constids.inc"
|
||||
|
||||
#undef X
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
static const ChipInfoPOD *get_chip_info(ArchArgs::ArchArgsTypes chip)
|
||||
{
|
||||
std::string chipdb;
|
||||
if (chip == ArchArgs::LCMXO2_256HC) {
|
||||
chipdb = "machxo2/chipdb-256.bin";
|
||||
} else if (chip == ArchArgs::LCMXO2_640HC) {
|
||||
chipdb = "machxo2/chipdb-640.bin";
|
||||
} else if (chip == ArchArgs::LCMXO2_1200HC) {
|
||||
chipdb = "machxo2/chipdb-1200.bin";
|
||||
} else if (chip == ArchArgs::LCMXO2_2000HC) {
|
||||
chipdb = "machxo2/chipdb-2000.bin";
|
||||
} else if (chip == ArchArgs::LCMXO2_4000HC) {
|
||||
chipdb = "machxo2/chipdb-4000.bin";
|
||||
} else if (chip == ArchArgs::LCMXO2_7000HC) {
|
||||
chipdb = "machxo2/chipdb-7000.bin";
|
||||
} else {
|
||||
log_error("Unknown chip\n");
|
||||
}
|
||||
|
||||
auto ptr = reinterpret_cast<const RelPtr<ChipInfoPOD> *>(get_chipdb(chipdb));
|
||||
if (ptr == nullptr)
|
||||
return nullptr;
|
||||
return ptr->get();
|
||||
}
|
||||
|
||||
bool Arch::isAvailable(ArchArgs::ArchArgsTypes chip) { return get_chip_info(chip) != nullptr; }
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
@ -265,22 +303,12 @@ const std::vector<GroupId> &Arch::getGroupGroups(GroupId group) const { return g
|
||||
|
||||
delay_t Arch::estimateDelay(WireId src, WireId dst) const
|
||||
{
|
||||
const WireInfo &s = wires.at(src);
|
||||
const WireInfo &d = wires.at(dst);
|
||||
int dx = abs(s.x - d.x);
|
||||
int dy = abs(s.y - d.y);
|
||||
return (dx + dy) * args.delayScale + args.delayOffset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
|
||||
{
|
||||
const auto &driver = net_info->driver;
|
||||
auto driver_loc = getBelLocation(driver.cell->bel);
|
||||
auto sink_loc = getBelLocation(sink.cell->bel);
|
||||
|
||||
int dx = abs(sink_loc.x - driver_loc.x);
|
||||
int dy = abs(sink_loc.y - driver_loc.y);
|
||||
return (dx + dy) * args.delayScale + args.delayOffset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; }
|
||||
|
@ -23,13 +23,55 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
/**** Everything in this section must be kept in sync with chipdb.py ****/
|
||||
|
||||
template <typename T> struct RelPtr
|
||||
{
|
||||
int32_t offset;
|
||||
|
||||
// void set(const T *ptr) {
|
||||
// offset = reinterpret_cast<const char*>(ptr) -
|
||||
// reinterpret_cast<const char*>(this);
|
||||
// }
|
||||
|
||||
const T *get() const { return reinterpret_cast<const T *>(reinterpret_cast<const char *>(this) + offset); }
|
||||
|
||||
const T &operator[](size_t index) const { return get()[index]; }
|
||||
|
||||
const T &operator*() const { return *(get()); }
|
||||
|
||||
const T *operator->() const { return get(); }
|
||||
};
|
||||
|
||||
|
||||
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||
int32_t stub;
|
||||
});
|
||||
|
||||
/************************ End of chipdb section. ************************/
|
||||
|
||||
struct ArchArgs
|
||||
{
|
||||
// Number of LUT inputs
|
||||
int K = 4;
|
||||
// y = mx + c relationship between distance and delay for interconnect
|
||||
// delay estimates
|
||||
double delayScale = 0.1, delayOffset = 0;
|
||||
enum ArchArgsTypes
|
||||
{
|
||||
NONE,
|
||||
LCMXO2_256HC,
|
||||
LCMXO2_640HC,
|
||||
LCMXO2_1200HC,
|
||||
LCMXO2_2000HC,
|
||||
LCMXO2_4000HC,
|
||||
LCMXO2_7000HC,
|
||||
} type = NONE;
|
||||
std::string package;
|
||||
enum SpeedGrade
|
||||
{
|
||||
SPEED_1 = 0,
|
||||
SPEED_2,
|
||||
SPEED_3,
|
||||
SPEED_4,
|
||||
SPEED_5,
|
||||
SPEED_6,
|
||||
} speed = SPEED_4;
|
||||
};
|
||||
|
||||
struct WireInfo;
|
||||
@ -146,6 +188,8 @@ struct Arch : BaseCtx
|
||||
ArchArgs args;
|
||||
Arch(ArchArgs args);
|
||||
|
||||
static bool isAvailable(ArchArgs::ArchArgsTypes chip);
|
||||
|
||||
std::string getChipName() const { return chipName; }
|
||||
|
||||
IdString archId() const { return id("generic"); }
|
||||
|
@ -42,11 +42,11 @@ std::unique_ptr<CellInfo> create_generic_cell(Context *ctx, IdString type, std::
|
||||
}
|
||||
new_cell->type = type;
|
||||
if (type == ctx->id("GENERIC_SLICE")) {
|
||||
new_cell->params[ctx->id("K")] = ctx->args.K;
|
||||
new_cell->params[ctx->id("K")] = 4;
|
||||
new_cell->params[ctx->id("INIT")] = 0;
|
||||
new_cell->params[ctx->id("FF_USED")] = 0;
|
||||
|
||||
for (int i = 0; i < ctx->args.K; i++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
add_port(ctx, new_cell.get(), "I[" + std::to_string(i) + "]", PORT_IN);
|
||||
|
||||
add_port(ctx, new_cell.get(), "CLK", PORT_IN);
|
||||
@ -73,7 +73,7 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
|
||||
lc->params[ctx->id("INIT")] = lut->params[ctx->id("INIT")];
|
||||
|
||||
int lut_k = int_or_default(lut->params, ctx->id("K"), 4);
|
||||
NPNR_ASSERT(lut_k <= ctx->args.K);
|
||||
NPNR_ASSERT(lut_k <= 4);
|
||||
|
||||
for (int i = 0; i < lut_k; i++) {
|
||||
IdString port = ctx->id("I[" + std::to_string(i) + "]");
|
||||
|
@ -27,11 +27,11 @@
|
||||
|
||||
USING_NEXTPNR_NAMESPACE
|
||||
|
||||
class GenericCommandHandler : public CommandHandler
|
||||
class MachXO2CommandHandler : public CommandHandler
|
||||
{
|
||||
public:
|
||||
GenericCommandHandler(int argc, char **argv);
|
||||
virtual ~GenericCommandHandler(){};
|
||||
MachXO2CommandHandler(int argc, char **argv);
|
||||
virtual ~MachXO2CommandHandler(){};
|
||||
std::unique_ptr<Context> createContext(std::unordered_map<std::string, Property> &values) override;
|
||||
void setupArchContext(Context *ctx) override{};
|
||||
void customBitstream(Context *ctx) override;
|
||||
@ -40,26 +40,48 @@ class GenericCommandHandler : public CommandHandler
|
||||
po::options_description getArchOptions() override;
|
||||
};
|
||||
|
||||
GenericCommandHandler::GenericCommandHandler(int argc, char **argv) : CommandHandler(argc, argv) {}
|
||||
MachXO2CommandHandler::MachXO2CommandHandler(int argc, char **argv) : CommandHandler(argc, argv) {}
|
||||
|
||||
po::options_description GenericCommandHandler::getArchOptions()
|
||||
po::options_description MachXO2CommandHandler::getArchOptions()
|
||||
{
|
||||
po::options_description specific("Architecture specific options");
|
||||
specific.add_options()("generic", "set device type to generic");
|
||||
if (Arch::isAvailable(ArchArgs::LCMXO2_256HC))
|
||||
specific.add_options()("256", "set device type to LCMXO2-256HC");
|
||||
if (Arch::isAvailable(ArchArgs::LCMXO2_640HC))
|
||||
specific.add_options()("640", "set device type to LCMXO2-640HC");
|
||||
if (Arch::isAvailable(ArchArgs::LCMXO2_1200HC))
|
||||
specific.add_options()("1200", "set device type to LCMXO2-1200HC");
|
||||
if (Arch::isAvailable(ArchArgs::LCMXO2_2000HC))
|
||||
specific.add_options()("2000", "set device type to LCMXO2-2000HC");
|
||||
if (Arch::isAvailable(ArchArgs::LCMXO2_4000HC))
|
||||
specific.add_options()("4000", "set device type to LCMXO2-4000HC");
|
||||
if (Arch::isAvailable(ArchArgs::LCMXO2_7000HC))
|
||||
specific.add_options()("7000", "set device type to LCMXO2-7000HC");
|
||||
|
||||
specific.add_options()("package", po::value<std::string>(), "select device package (defaults to QFN32)");
|
||||
specific.add_options()("speed", po::value<int>(), "select device speedgrade (1 to 6 inclusive)");
|
||||
|
||||
specific.add_options()("override-basecfg", po::value<std::string>(),
|
||||
"base chip configuration in Trellis text format");
|
||||
specific.add_options()("textcfg", po::value<std::string>(), "textual configuration in Trellis format to write");
|
||||
|
||||
specific.add_options()("lpf", po::value<std::vector<std::string>>(), "LPF pin constraint file(s)");
|
||||
|
||||
specific.add_options()("no-iobs", "disable automatic IO buffer insertion");
|
||||
return specific;
|
||||
}
|
||||
|
||||
void GenericCommandHandler::customBitstream(Context *ctx) {}
|
||||
void MachXO2CommandHandler::customBitstream(Context *ctx) {}
|
||||
|
||||
std::unique_ptr<Context> GenericCommandHandler::createContext(std::unordered_map<std::string, Property> &values)
|
||||
std::unique_ptr<Context> MachXO2CommandHandler::createContext(std::unordered_map<std::string, Property> &values)
|
||||
{
|
||||
ArchArgs chipArgs;
|
||||
if (values.find("arch.name") != values.end()) {
|
||||
std::string arch_name = values["arch.name"].as_string();
|
||||
if (arch_name != "generic")
|
||||
if (arch_name != "machxo2")
|
||||
log_error("Unsuported architecture '%s'.\n", arch_name.c_str());
|
||||
}
|
||||
|
||||
auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
||||
if (vm.count("no-iobs"))
|
||||
ctx->settings[ctx->id("disable_iobs")] = Property::State::S1;
|
||||
@ -68,7 +90,7 @@ std::unique_ptr<Context> GenericCommandHandler::createContext(std::unordered_map
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
GenericCommandHandler handler(argc, argv);
|
||||
MachXO2CommandHandler handler(argc, argv);
|
||||
return handler.exec();
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ static void pack_constants(Context *ctx)
|
||||
log_info("Packing constants..\n");
|
||||
|
||||
std::unique_ptr<CellInfo> gnd_cell = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), "$PACKER_GND");
|
||||
gnd_cell->params[ctx->id("INIT")] = Property(0, 1 << ctx->args.K);
|
||||
gnd_cell->params[ctx->id("INIT")] = Property(0, 1 << 4);
|
||||
std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo);
|
||||
gnd_net->name = ctx->id("$PACKER_GND_NET");
|
||||
gnd_net->driver.cell = gnd_cell.get();
|
||||
@ -147,7 +147,7 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
std::unique_ptr<CellInfo> vcc_cell = create_generic_cell(ctx, ctx->id("GENERIC_SLICE"), "$PACKER_VCC");
|
||||
// Fill with 1s
|
||||
vcc_cell->params[ctx->id("INIT")] = Property(Property::S1).extract(0, (1 << ctx->args.K), Property::S1);
|
||||
vcc_cell->params[ctx->id("INIT")] = Property(Property::S1).extract(0, (1 << 4), Property::S1);
|
||||
std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo);
|
||||
vcc_net->name = ctx->id("$PACKER_VCC_NET");
|
||||
vcc_net->driver.cell = vcc_cell.get();
|
||||
|
Loading…
Reference in New Issue
Block a user