ecp5: Conservative analysis of comb DSP timing

Signed-off-by: David Shah <dave@ds0.me>
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 5b3cc66..cb1a3cc 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -701,6 +701,13 @@
         return false;
     } else if (cell->type == id_DP16KD) {
         return false;
+    } else if (cell->type == id_MULT18X18D) {
+        std::string fn = fromPort.str(this), tn = toPort.str(this);
+        if (fn.size() > 1 && (fn.front() == 'A' || fn.front() == 'B') && std::isdigit(fn.at(1))) {
+            if (tn.size() > 1 && tn.front() == 'P' && std::isdigit(tn.at(1)))
+                return getDelayFromTimingDatabase(id_MULT18X18D_REGS_NONE, id(std::string("") + fn.front()), id_P, delay);
+        }
+        return false;
     } else if (cell->type == id_IOLOGIC || cell->type == id_SIOLOGIC) {
         return false;
     } else {
@@ -778,7 +785,16 @@
         }
         NPNR_ASSERT_FALSE_STR("no timing type for RAM port '" + port.str(this) + "'");
     } else if (cell->type == id_MULT18X18D) {
-        return TMG_IGNORE; // FIXME
+        if (port == id_CLK0 || port == id_CLK1 || port == id_CLK2 || port == id_CLK3)
+            return TMG_CLOCK_INPUT;
+        std::string pname = port.str(this);
+        if (pname.size() > 1) {
+            if ((pname.front() == 'A' || pname.front() == 'B') && std::isdigit(pname.at(1)))
+                return TMG_COMB_INPUT;
+            if (pname.front() == 'P' && std::isdigit(pname.at(1)))
+                return TMG_COMB_OUTPUT;
+        }
+        return TMG_IGNORE;
     } else if (cell->type == id_ALU54B) {
         return TMG_IGNORE; // FIXME
     } else if (cell->type == id_EHXPLLL) {
diff --git a/ecp5/constids.inc b/ecp5/constids.inc
index 8a3179b..007e952 100644
--- a/ecp5/constids.inc
+++ b/ecp5/constids.inc
@@ -1281,4 +1281,11 @@
 X(WRCFLAG)
 X(SCLK)
 
-X(TRELLIS_ECLKBUF)
\ No newline at end of file
+X(TRELLIS_ECLKBUF)
+
+X(MULT18X18D_REGS_ALL)
+X(MULT18X18D_REGS_INPUT)
+X(MULT18X18D_REGS_NONE)
+X(MULT18X18D_REGS_OUTPUT)
+X(MULT18X18D_REGS_PIPELINE)
+X(P)
\ No newline at end of file