From 9704f422dcae5788d39edf35addd6ee5e9dfd428 Mon Sep 17 00:00:00 2001
From: "William D. Jones" <thor0505@comcast.net>
Date: Sat, 27 Jun 2020 19:22:58 -0400
Subject: machxo2: Start creating MachXO2CommandHandler.

---
 machxo2/arch.cc  | 54 +++++++++++++++++++++++++++++++++++++++++-------------
 machxo2/arch.h   | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 machxo2/cells.cc |  6 +++---
 machxo2/main.cc  | 42 ++++++++++++++++++++++++++++++++----------
 machxo2/pack.cc  |  4 ++--
 5 files changed, 127 insertions(+), 33 deletions(-)

diff --git a/machxo2/arch.cc b/machxo2/arch.cc
index 56899ced..70de80cf 100644
--- a/machxo2/arch.cc
+++ b/machxo2/arch.cc
@@ -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; }
diff --git a/machxo2/arch.h b/machxo2/arch.h
index ba34f8dc..b8b9ce85 100644
--- a/machxo2/arch.h
+++ b/machxo2/arch.h
@@ -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"); }
diff --git a/machxo2/cells.cc b/machxo2/cells.cc
index c4421f90..21c233d0 100644
--- a/machxo2/cells.cc
+++ b/machxo2/cells.cc
@@ -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) + "]");
diff --git a/machxo2/main.cc b/machxo2/main.cc
index bb780996..84b99edc 100644
--- a/machxo2/main.cc
+++ b/machxo2/main.cc
@@ -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();
 }
 
diff --git a/machxo2/pack.cc b/machxo2/pack.cc
index 43157b6c..b995375a 100644
--- a/machxo2/pack.cc
+++ b/machxo2/pack.cc
@@ -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();
-- 
cgit v1.2.3