diff options
| author | David Shah <dave@ds0.me> | 2020-12-08 09:26:09 +0000 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-08 09:26:09 +0000 | 
| commit | ca08add9c90b14e4fb8d63ccb4f475dccd598d66 (patch) | |
| tree | 46672f7f931f5e005891d1d4d96b2978f9036add | |
| parent | 92ef01830c9f92d1374b4d02965865f11fab0ccc (diff) | |
| parent | 588042dc997080830e73c10b71c15444756dbeab (diff) | |
| download | nextpnr-ca08add9c90b14e4fb8d63ccb4f475dccd598d66.tar.gz nextpnr-ca08add9c90b14e4fb8d63ccb4f475dccd598d66.tar.bz2 nextpnr-ca08add9c90b14e4fb8d63ccb4f475dccd598d66.zip | |
Merge pull request #528 from YosysHQ/dave/nexus-lram
nexus: Add basic LRAM support
| -rw-r--r-- | nexus/arch.cc | 11 | ||||
| -rw-r--r-- | nexus/arch.h | 28 | ||||
| -rw-r--r-- | nexus/constids.inc | 21 | ||||
| -rw-r--r-- | nexus/fasm.cc | 40 | ||||
| -rw-r--r-- | nexus/pack.cc | 60 | ||||
| -rw-r--r-- | nexus/pins.cc | 23 | 
6 files changed, 167 insertions, 16 deletions
| diff --git a/nexus/arch.cc b/nexus/arch.cc index f222a5ad..dbc12c13 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -619,6 +619,10 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const          bb.x0 = std::max<int>(0, bb.x0 - 6);          bb.x1 = std::min<int>(chip_info->width, bb.x1 + 6);      } +    if (lram_wires.count(src) || lram_wires.count(dst)) { +        bb.y0 = std::max<int>(0, bb.y0 - 7); +        bb.y1 = std::min<int>(chip_info->width, bb.y1 + 7); +    }      return bb;  } @@ -669,6 +673,13 @@ void Arch::pre_routing()                      dsp_wires.insert(wire);              }          } +        if (ci->type == id_LRAM_CORE) { +            for (auto port : sorted_ref(ci->ports)) { +                WireId wire = getBelPinWire(ci->bel, port.first); +                if (wire != WireId()) +                    lram_wires.insert(wire); +            } +        }      }  } diff --git a/nexus/arch.h b/nexus/arch.h index d4d4799e..2bc56b53 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -838,18 +838,20 @@ enum CellPinStyle      PINBIT_1 = 0x2000,      // pin has an explicit bit that must be set if tied to 1      PINBIT_CIBMUX = 0x4000, // pin's CIBMUX must be floating for pin to be 1 -    PINSTYLE_NONE = 0x0000, // default -    PINSTYLE_CIB = 0x4012,  // 'CIB' signal, floats high but explicitly zeroed if not used -    PINSTYLE_CLK = 0x0107,  // CLK type signal, invertible and defaults to disconnected -    PINSTYLE_CE = 0x0027,   // CE type signal, invertible and defaults to enabled -    PINSTYLE_LSR = 0x0017,  // LSR type signal, invertible and defaults to not reset -    PINSTYLE_DEDI = 0x0000, // dedicated signals, leave alone -    PINSTYLE_PU = 0x4022,   // signals that float high and default high -    PINSTYLE_T = 0x4027,    // PIO 'T' signal - -    PINSTYLE_ADLSB = 0x4017,  // special case of the EBR address MSBs -    PINSTYLE_INV_PD = 0x0017, // invertible, pull down by default -    PINSTYLE_INV_PU = 0x4027, // invertible, pull up by default +    PINSTYLE_NONE = 0x0000,      // default +    PINSTYLE_CIB = 0x4012,       // 'CIB' signal, floats high but explicitly zeroed if not used +    PINSTYLE_CLK = 0x0107,       // CLK type signal, invertible and defaults to disconnected +    PINSTYLE_CE = 0x0027,        // CE type signal, invertible and defaults to enabled +    PINSTYLE_LSR = 0x0017,       // LSR type signal, invertible and defaults to not reset +    PINSTYLE_DEDI = 0x0000,      // dedicated signals, leave alone +    PINSTYLE_PU = 0x4022,        // signals that float high and default high +    PINSTYLE_PU_NONCIB = 0x0022, // signals that float high and default high +    PINSTYLE_T = 0x4027,         // PIO 'T' signal + +    PINSTYLE_ADLSB = 0x4017,      // special case of the EBR address MSBs +    PINSTYLE_INV_PD = 0x0017,     // invertible, pull down by default +    PINSTYLE_INV_PD_CIB = 0x4017, // invertible, pull down by default +    PINSTYLE_INV_PU = 0x4027,     // invertible, pull up by default      PINSTYLE_IOL_CE = 0x2027, // CE type signal, with explicit 'const-1' config bit      PINSTYLE_GATE = 0x1011,   // gated signal that defaults to 0 @@ -1363,7 +1365,7 @@ struct Arch : BaseCtx      // for better DSP bounding boxes      void pre_routing(); -    std::unordered_set<WireId> dsp_wires; +    std::unordered_set<WireId> dsp_wires, lram_wires;      // ------------------------------------------------- diff --git a/nexus/constids.inc b/nexus/constids.inc index f8939263..e4901692 100644 --- a/nexus/constids.inc +++ b/nexus/constids.inc @@ -443,3 +443,24 @@ X(DIVF)  X(REF_MMD_DIG)  X(FBK_MMD_DIG)  X(CLKMUX_FB) + +X(LRAM_CORE) + +X(EBR_SP_EN) +X(ECC_BYTE_SEL) +X(CS) +X(CSA) +X(CSB) +X(CSR) +X(CSW) +X(OCEA) +X(OCEB) +X(RSTR) +X(DPS) +X(IGN) +X(INITN) +X(STDBYN) +X(TBISTN) +X(WE) +X(CEOUTA) +X(CEOUTB) diff --git a/nexus/fasm.cc b/nexus/fasm.cc index fcbe0b8c..b041bf43 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -596,6 +596,44 @@ struct NexusFasmWriter          }          pop();      } +    // Write out config for an LRAM_CORE cell +    void write_lram(const CellInfo *cell) +    { +        BelId bel = cell->bel; +        push_bel(bel); +        write_enum(cell, "ASYNC_RST_RELEASE", "SYNC"); +        write_enum(cell, "EBR_SP_EN", "DISABLE"); +        write_enum(cell, "ECC_BYTE_SEL", "BYTE_EN"); +        write_enum(cell, "GSR", "DISABLED"); +        write_enum(cell, "OUT_REGMODE_A", "NO_REG"); +        write_enum(cell, "OUT_REGMODE_B", "NO_REG"); +        write_enum(cell, "RESETMODE", "SYNC"); +        write_enum(cell, "UNALIGNED_READ", "DISABLE"); +        write_cell_muxes(cell); +        pop(); +        blank(); + +        Loc l = ctx->getBelLocation(bel); +        push(stringf("IP_LRAM_CORE_R%dC%d", l.y, l.x)); +        for (int i = 0; i < 128; i++) { +            IdString param = ctx->id(stringf("INITVAL_%02X", i)); +            if (!cell->params.count(param)) +                continue; +            auto &prop = cell->params.at(param); +            std::string value; +            if (prop.is_string) { +                NPNR_ASSERT(prop.str.substr(0, 2) == "0x"); +                // Lattice-style hex string +                value = prop.str.substr(2); +                value = stringf("5120'h%s", value.c_str()); +            } else { +                // True Verilog bitvector +                value = stringf("5120'b%s", prop.str.c_str()); +            } +            write_bit(stringf("INITVAL_%02X[5119:0] = %s", i, value.c_str())); +        } +        pop(); +    }      // Write out FASM for unused bels where needed      void write_unused()      { @@ -710,6 +748,8 @@ struct NexusFasmWriter                  write_dsp(ci);              else if (ci->type == id_PLL_CORE)                  write_pll(ci); +            else if (ci->type == id_LRAM_CORE) +                write_lram(ci);              blank();          }          // Write config for unused bels diff --git a/nexus/pack.cc b/nexus/pack.cc index eb1ac560..9bb90592 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -1024,8 +1024,9 @@ struct NexusPacker      {          // Convert primitives from their non-CORE variant to their CORE variant          static const std::unordered_map<IdString, IdString> prim_map = { -                {id_OSCA, id_OSC_CORE},          {id_DP16K, id_DP16K_MODE}, {id_PDP16K, id_PDP16K_MODE}, -                {id_PDPSC16K, id_PDPSC16K_MODE}, {id_SP16K, id_SP16K_MODE}, {id_FIFO16K, id_FIFO16K_MODE}, +                {id_OSCA, id_OSC_CORE},          {id_DP16K, id_DP16K_MODE},       {id_PDP16K, id_PDP16K_MODE}, +                {id_PDPSC16K, id_PDPSC16K_MODE}, {id_SP16K, id_SP16K_MODE},       {id_FIFO16K, id_FIFO16K_MODE}, +                {id_SP512K, id_SP512K_MODE},     {id_DPSC512K, id_DPSC512K_MODE}, {id_PDPSC512K, id_PDPSC512K_MODE},                  {id_PLL, id_PLL_CORE},          }; @@ -1092,6 +1093,60 @@ struct NexusPacker          }      } +    void pack_lram() +    { +        std::unordered_map<IdString, XFormRule> lram_rules; +        lram_rules[id_SP512K_MODE].new_type = id_LRAM_CORE; +        lram_rules[id_SP512K_MODE].set_params.emplace_back(id_EBR_SP_EN, std::string("ENABLE")); +        lram_rules[id_SP512K_MODE].port_xform[id_CE] = id_CEA; +        lram_rules[id_SP512K_MODE].port_xform[id_CS] = id_CSA; +        lram_rules[id_SP512K_MODE].port_xform[id_WE] = id_WEA; +        lram_rules[id_SP512K_MODE].port_xform[id_RSTOUT] = id_RSTA; +        lram_rules[id_SP512K_MODE].port_xform[id_CEOUT] = id_OCEA; +        add_bus_xform(lram_rules[id_SP512K_MODE], "DI", "DIA", 32); +        add_bus_xform(lram_rules[id_SP512K_MODE], "DO", "DOA", 32); +        add_bus_xform(lram_rules[id_SP512K_MODE], "AD", "ADA", 14); +        add_bus_xform(lram_rules[id_SP512K_MODE], "BYTEEN_N", "BENA_N", 4); + +        lram_rules[id_PDPSC512K_MODE].new_type = id_LRAM_CORE; +        lram_rules[id_PDPSC512K_MODE].port_xform[id_CEW] = id_CEA; +        lram_rules[id_PDPSC512K_MODE].port_xform[id_CSW] = id_CSA; +        lram_rules[id_PDPSC512K_MODE].port_xform[id_CER] = id_CEB; +        lram_rules[id_PDPSC512K_MODE].port_xform[id_CSR] = id_CSB; +        lram_rules[id_PDPSC512K_MODE].port_xform[id_WE] = id_WEA; +        lram_rules[id_PDPSC512K_MODE].port_xform[id_RSTR] = id_RSTB; +        add_bus_xform(lram_rules[id_PDPSC512K_MODE], "DI", "DIA", 32); +        add_bus_xform(lram_rules[id_PDPSC512K_MODE], "DO", "DOB", 32); +        add_bus_xform(lram_rules[id_PDPSC512K_MODE], "ADW", "ADA", 14); +        add_bus_xform(lram_rules[id_PDPSC512K_MODE], "ADR", "ADB", 14); +        add_bus_xform(lram_rules[id_PDPSC512K_MODE], "BYTEEN_N", "BENA_N", 4); + +        lram_rules[id_DPSC512K_MODE].new_type = id_LRAM_CORE; +        lram_rules[id_DPSC512K_MODE].port_xform[id_CEOUTA] = id_OCEA; +        lram_rules[id_DPSC512K_MODE].port_xform[id_CEOUTB] = id_OCEB; + +        log_info("Packing LRAM...\n"); +        generic_xform(lram_rules, true); + +        for (auto cell : sorted(ctx->cells)) { +            CellInfo *ci = cell.second; +            if (ci->type != id_LRAM_CORE) +                continue; +            if (str_or_default(ci->params, ctx->id("ECC_BYTE_SEL"), "BYTE_EN") == "BYTE_EN") +                continue; +            for (int i = 0; i < 0x80; i++) { +                // FIXME: document ECC and remove this DRC +                std::string name = stringf("INITVAL_%02X", i); +                if (!ci->params.count(ctx->id(name))) +                    continue; +                if (ci->params.at(ctx->id(name)).str.find_last_not_of("0x") == std::string::npos) +                    continue; +                log_error("LRAM initialisation is currently unsupported in ECC mode (to disable ECC, set ECC_BYTE_SEL " +                          "to BYTE_EN).\n"); +            } +        } +    } +      void pack_widefn()      {          std::vector<CellInfo *> widefns; @@ -1883,6 +1938,7 @@ struct NexusPacker          pack_dsps();          convert_prims();          pack_bram(); +        pack_lram();          pack_lutram();          pack_carries();          pack_widefn(); diff --git a/nexus/pins.cc b/nexus/pins.cc index 05bffb1e..0e27214b 100644 --- a/nexus/pins.cc +++ b/nexus/pins.cc @@ -168,7 +168,28 @@ static const std::unordered_map<IdString, Arch::CellPinsData> base_cell_pin_data                   {id_ENEXT, PINSTYLE_DEDI},                   {{}, PINSTYLE_CIB},           }}, -}; +        {id_LRAM_CORE, +         { +                 {id_CLK, PINSTYLE_CLK}, +                 {id_CEA, PINSTYLE_PU_NONCIB}, +                 {id_CEB, PINSTYLE_PU_NONCIB}, +                 {id_OCEA, PINSTYLE_PU}, +                 {id_OCEB, PINSTYLE_PU}, +                 {id_CSA, PINSTYLE_PU}, +                 {id_CSB, PINSTYLE_PU}, +                 {id_RSTA, PINSTYLE_LSR}, +                 {id_RSTB, PINSTYLE_LSR}, +                 {id_WEA, PINSTYLE_INV_PD_CIB}, +                 {id_WEB, PINSTYLE_INV_PD_CIB}, +                 {id_IGN, PINSTYLE_PU}, +                 {id_INITN, PINSTYLE_PU}, +                 {id_STDBYN, PINSTYLE_PU}, +                 {id_TBISTN, PINSTYLE_PU}, +                 {id_SCANCLK, PINSTYLE_DEDI}, +                 {id_SCANRST, PINSTYLE_DEDI}, +                 {id_OPCGLDCK, PINSTYLE_DEDI}, +                 {{}, PINSTYLE_CIB}, +         }}};  } // namespace  void Arch::init_cell_pin_data() { cell_pins_db = base_cell_pin_data; } | 
