From acddc363896d88ae8cf99879467ad91d618f6215 Mon Sep 17 00:00:00 2001 From: Chun Lin Min Date: Tue, 2 Jul 2024 12:44:30 -0700 Subject: [PATCH] add PolarFire FPGA support --- passes/pmgen/Makefile.inc | 11 + passes/pmgen/mchp_dsp.cc | 373 ++++++++ passes/pmgen/mchp_dsp.pmg | 440 +++++++++ passes/pmgen/mchp_dsp_CREG.pmg | 169 ++++ passes/pmgen/mchp_dsp_cascade.pmg | 238 +++++ techlibs/mchp/LSRAM.txt | 191 ++++ techlibs/mchp/LSRAM_map.v | 323 +++++++ techlibs/mchp/Makefile.inc | 31 + techlibs/mchp/arith_map.v | 105 +++ techlibs/mchp/brams_defs.vh | 48 + techlibs/mchp/cells_map.v | 104 +++ techlibs/mchp/cells_sim.v | 849 ++++++++++++++++++ techlibs/mchp/mchp_dffopt.cc | 340 +++++++ techlibs/mchp/pf_dsp_map.v | 95 ++ techlibs/mchp/synth_mchp.cc | 543 +++++++++++ techlibs/mchp/tests/Registers/Registers.v | 38 + techlibs/mchp/tests/Registers/Registers.ys | 23 + techlibs/mchp/tests/carryout/carryout.v | 34 + techlibs/mchp/tests/carryout/carryout.ys | 21 + techlibs/mchp/tests/cascade/cascade.v | 38 + techlibs/mchp/tests/cascade/cascade.ys | 21 + techlibs/mchp/tests/dff_opt/dff_opt.v | 42 + techlibs/mchp/tests/dff_opt/dff_opt.ys | 21 + techlibs/mchp/tests/full_dsp/full_dsp.v | 30 + techlibs/mchp/tests/full_dsp/full_dsp.ys | 21 + techlibs/mchp/tests/large_mult/large_mult.v | 25 + techlibs/mchp/tests/large_mult/large_mult.ys | 21 + techlibs/mchp/tests/mac/mac.v | 43 + techlibs/mchp/tests/mac/mac.ys | 24 + .../mchp/tests/postAdd_mult/postAdd_mult.v | 30 + .../mchp/tests/postAdd_mult/postAdd_mult.ys | 21 + techlibs/mchp/tests/post_adder/post_adder.v | 32 + techlibs/mchp/tests/post_adder/post_adder.ys | 21 + .../mchp/tests/pre_adder_dsp/pre_adder_dsp.v | 30 + .../mchp/tests/pre_adder_dsp/pre_adder_dsp.ys | 21 + techlibs/mchp/tests/ram_SDP/ram_SDP.v | 39 + techlibs/mchp/tests/ram_SDP/ram_SDP.ys | 21 + techlibs/mchp/tests/ram_TDP/ram_TDP.v | 56 ++ techlibs/mchp/tests/ram_TDP/ram_TDP.ys | 21 + techlibs/mchp/tests/reduce/reduce.v | 29 + techlibs/mchp/tests/reduce/reduce.ys | 21 + techlibs/mchp/tests/reg_c/reg_c.v | 122 +++ techlibs/mchp/tests/reg_c/reg_c.ys | 21 + techlibs/mchp/tests/reg_test/reg_test.v | 97 ++ techlibs/mchp/tests/reg_test/reg_test.ys | 21 + techlibs/mchp/tests/signed_mult/signed_mult.v | 28 + .../mchp/tests/signed_mult/signed_mult.ys | 21 + techlibs/mchp/tests/simple_ram/simple_ram.v | 37 + techlibs/mchp/tests/simple_ram/simple_ram.ys | 21 + .../mchp/tests/unsigned_mult/unsigned_mult.v | 28 + .../mchp/tests/unsigned_mult/unsigned_mult.ys | 21 + techlibs/mchp/tests/uram_ar/uram_ar.v | 38 + techlibs/mchp/tests/uram_ar/uram_ar.ys | 21 + techlibs/mchp/tests/uram_sr/uram_sr.v | 32 + techlibs/mchp/tests/uram_sr/uram_sr.ys | 21 + techlibs/mchp/tests/widemux/widemux.v | 48 + techlibs/mchp/tests/widemux/widemux.ys | 21 + techlibs/mchp/uSRAM.txt | 69 ++ techlibs/mchp/uSRAM_map.v | 118 +++ 59 files changed, 5389 insertions(+) create mode 100644 passes/pmgen/mchp_dsp.cc create mode 100644 passes/pmgen/mchp_dsp.pmg create mode 100644 passes/pmgen/mchp_dsp_CREG.pmg create mode 100644 passes/pmgen/mchp_dsp_cascade.pmg create mode 100644 techlibs/mchp/LSRAM.txt create mode 100644 techlibs/mchp/LSRAM_map.v create mode 100644 techlibs/mchp/Makefile.inc create mode 100644 techlibs/mchp/arith_map.v create mode 100644 techlibs/mchp/brams_defs.vh create mode 100644 techlibs/mchp/cells_map.v create mode 100644 techlibs/mchp/cells_sim.v create mode 100644 techlibs/mchp/mchp_dffopt.cc create mode 100644 techlibs/mchp/pf_dsp_map.v create mode 100644 techlibs/mchp/synth_mchp.cc create mode 100644 techlibs/mchp/tests/Registers/Registers.v create mode 100644 techlibs/mchp/tests/Registers/Registers.ys create mode 100644 techlibs/mchp/tests/carryout/carryout.v create mode 100644 techlibs/mchp/tests/carryout/carryout.ys create mode 100644 techlibs/mchp/tests/cascade/cascade.v create mode 100644 techlibs/mchp/tests/cascade/cascade.ys create mode 100644 techlibs/mchp/tests/dff_opt/dff_opt.v create mode 100644 techlibs/mchp/tests/dff_opt/dff_opt.ys create mode 100644 techlibs/mchp/tests/full_dsp/full_dsp.v create mode 100644 techlibs/mchp/tests/full_dsp/full_dsp.ys create mode 100644 techlibs/mchp/tests/large_mult/large_mult.v create mode 100644 techlibs/mchp/tests/large_mult/large_mult.ys create mode 100644 techlibs/mchp/tests/mac/mac.v create mode 100644 techlibs/mchp/tests/mac/mac.ys create mode 100644 techlibs/mchp/tests/postAdd_mult/postAdd_mult.v create mode 100644 techlibs/mchp/tests/postAdd_mult/postAdd_mult.ys create mode 100644 techlibs/mchp/tests/post_adder/post_adder.v create mode 100644 techlibs/mchp/tests/post_adder/post_adder.ys create mode 100644 techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.v create mode 100644 techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.ys create mode 100644 techlibs/mchp/tests/ram_SDP/ram_SDP.v create mode 100644 techlibs/mchp/tests/ram_SDP/ram_SDP.ys create mode 100644 techlibs/mchp/tests/ram_TDP/ram_TDP.v create mode 100644 techlibs/mchp/tests/ram_TDP/ram_TDP.ys create mode 100644 techlibs/mchp/tests/reduce/reduce.v create mode 100644 techlibs/mchp/tests/reduce/reduce.ys create mode 100644 techlibs/mchp/tests/reg_c/reg_c.v create mode 100644 techlibs/mchp/tests/reg_c/reg_c.ys create mode 100644 techlibs/mchp/tests/reg_test/reg_test.v create mode 100644 techlibs/mchp/tests/reg_test/reg_test.ys create mode 100755 techlibs/mchp/tests/signed_mult/signed_mult.v create mode 100755 techlibs/mchp/tests/signed_mult/signed_mult.ys create mode 100644 techlibs/mchp/tests/simple_ram/simple_ram.v create mode 100644 techlibs/mchp/tests/simple_ram/simple_ram.ys create mode 100644 techlibs/mchp/tests/unsigned_mult/unsigned_mult.v create mode 100644 techlibs/mchp/tests/unsigned_mult/unsigned_mult.ys create mode 100644 techlibs/mchp/tests/uram_ar/uram_ar.v create mode 100644 techlibs/mchp/tests/uram_ar/uram_ar.ys create mode 100644 techlibs/mchp/tests/uram_sr/uram_sr.v create mode 100644 techlibs/mchp/tests/uram_sr/uram_sr.ys create mode 100644 techlibs/mchp/tests/widemux/widemux.v create mode 100644 techlibs/mchp/tests/widemux/widemux.ys create mode 100644 techlibs/mchp/uSRAM.txt create mode 100644 techlibs/mchp/uSRAM_map.v diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index ed872b721..581ce2416 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -37,6 +37,17 @@ $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_cascade_pm.h)) # -------------------------------------- +OBJS += passes/pmgen/mchp_dsp.o +GENFILES += passes/pmgen/mchp_dsp_pm.h +GENFILES += passes/pmgen/mchp_dsp_CREG_pm.h +GENFILES += passes/pmgen/mchp_dsp_cascade_pm.h +passes/pmgen/mchp_dsp.o: passes/pmgen/mchp_dsp_pm.h passes/pmgen/mchp_dsp_CREG_pm.h passes/pmgen/mchp_dsp_cascade_pm.h +$(eval $(call add_extra_objs,passes/pmgen/mchp_dsp_pm.h)) +$(eval $(call add_extra_objs,passes/pmgen/mchp_dsp_CREG_pm.h)) +$(eval $(call add_extra_objs,passes/pmgen/mchp_dsp_cascade_pm.h)) + +# -------------------------------------- + OBJS += passes/pmgen/peepopt.o GENFILES += passes/pmgen/peepopt_pm.h passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h diff --git a/passes/pmgen/mchp_dsp.cc b/passes/pmgen/mchp_dsp.cc new file mode 100644 index 000000000..8a1bf0b3c --- /dev/null +++ b/passes/pmgen/mchp_dsp.cc @@ -0,0 +1,373 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +#include "passes/pmgen/mchp_dsp_pm.h" +#include "passes/pmgen/mchp_dsp_CREG_pm.h" +#include "passes/pmgen/mchp_dsp_cascade_pm.h" + +void mchp_dsp_pack(mchp_dsp_pm &pm) +{ + auto &st = pm.st_mchp_dsp_pack; + + log("Analysing %s.%s for MCHP MACC_PA packing.\n", log_id(pm.module), log_id(st.dsp)); + + Cell *cell = st.dsp; + //pack pre-adder + if (st.preAdderStatic) { + SigSpec &pasub = cell->connections_.at(ID(PASUB)); + log(" static PASUB preadder %s (%s)\n", log_id(st.preAdderStatic), log_id(st.preAdderStatic->type)); + bool D_SIGNED = st.preAdderStatic->getParam(ID::B_SIGNED).as_bool(); + bool B_SIGNED = st.preAdderStatic->getParam(ID::A_SIGNED).as_bool(); + st.sigB.extend_u0(18, B_SIGNED); + st.sigD.extend_u0(18, D_SIGNED); + if (st.moveBtoA) + { + cell->setPort(ID::A, st.sigA); // if pre-adder feeds into A, original sigB will be moved to port A + } + cell->setPort(ID::B, st.sigB); + cell->setPort(ID::D, st.sigD); + // MACC_PA supports both addition and subtraction with the pre-adder. + // Affects the sign of the 'D' port. + if (st.preAdderStatic->type == ID($add)) + pasub[0] = State::S0; + else if (st.preAdderStatic->type == ID($sub)) + pasub[0] = State::S1; + else + log_assert(!"strange pre-adder type"); + + pm.autoremove(st.preAdderStatic); + } + //pack post-adder + if (st.postAdderStatic) { + log(" postadder %s (%s)\n", log_id(st.postAdderStatic), log_id(st.postAdderStatic->type)); + SigSpec &sub = cell->connections_.at(ID(SUB)); + // Post-adder in MACC_PA also supports subtraction + // Determines the sign of the output from the multiplier. + if (st.postAdderStatic->type == ID($add)) + sub[0] = State::S0; + else if (st.postAdderStatic->type == ID($sub)) + sub[0] = State::S1; + else + log_assert(!"strange post-adder type"); + + if (st.useFeedBack) { + cell->setPort(ID(CDIN_FDBK_SEL), {State::S0, State::S1}); + } else { + st.sigC.extend_u0(48, st.postAdderStatic->getParam(ID::A_SIGNED).as_bool()); + cell->setPort(ID::C, st.sigC); + } + + + pm.autoremove(st.postAdderStatic); + } + + // pack registers + if (st.clock != SigBit()) + { + cell->setPort(ID::CLK, st.clock); + + // function to absorb a register + auto f = [&pm,cell](SigSpec &A, Cell* ff, IdString ceport, IdString rstport, IdString bypass) { + + // input/output ports + SigSpec D = ff->getPort(ID::D); + SigSpec Q = pm.sigmap(ff->getPort(ID::Q)); + + if (!A.empty()) + A.replace(Q, D); + if (rstport != IdString()) { + if (ff->type.in(ID($sdff), ID($sdffe))) { + SigSpec srst = ff->getPort(ID::SRST); + bool rstpol_n = !ff->getParam(ID::SRST_POLARITY).as_bool(); + // active low sync rst + cell->setPort(rstport, rstpol_n ? srst : pm.module->Not(NEW_ID, srst)); + } else if (ff->type.in(ID($adff), ID($adffe))) { + SigSpec arst = ff->getPort(ID::ARST); + bool rstpol_n = !ff->getParam(ID::ARST_POLARITY).as_bool(); + // active low async rst + cell->setPort(rstport, rstpol_n ? arst : pm.module->Not(NEW_ID, arst)); + } else { + // active low async/sync rst + cell->setPort(rstport, State::S1); + } + } + if (ff->type.in(ID($dffe), ID($sdffe), ID($adffe))) { + SigSpec ce = ff->getPort(ID::EN); + bool cepol = ff->getParam(ID::EN_POLARITY).as_bool(); + // enables are all active high + cell->setPort(ceport, cepol ? ce : pm.module->Not(NEW_ID, ce)); + } + else { + // enables are all active high + cell->setPort(ceport, State::S1); + } + + // bypass set to 0 + cell->setPort(bypass, State::S0); + + + for (auto c : Q.chunks()) { + auto it = c.wire->attributes.find(ID::init); + if (it == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset+c.width; i++) { + log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); + it->second[i] = State::Sx; + } + } + }; + + // NOTE: flops are not autoremoved because it is possible that they + // are only partially absorbed into DSP, or have fanouts. + if (st.ffA) { + SigSpec A = cell->getPort(ID::A); + if (st.ffA) { + f(A, st.ffA, ID(A_EN), ID(A_SRST_N), ID(A_BYPASS)); + } + pm.add_siguser(A, cell); + cell->setPort(ID::A, A); + } + if (st.ffB) { + SigSpec B = cell->getPort(ID::B); + if (st.ffB) { + f(B, st.ffB, ID(B_EN), ID(B_SRST_N), ID(B_BYPASS)); + } + pm.add_siguser(B, cell); + cell->setPort(ID::B, B); + } + if (st.ffD) { + SigSpec D = cell->getPort(ID::D); + if (st.ffD->type.in(ID($adff), ID($adffe))) { + f(D, st.ffD, ID(D_EN), ID(D_ARST_N), ID(D_BYPASS)); + } else { + f(D, st.ffD, ID(D_EN), ID(D_SRST_N), ID(D_BYPASS)); + } + + pm.add_siguser(D, cell); + cell->setPort(ID::D, D); + } + if (st.ffP) { + SigSpec P; // unused + f(P, st.ffP, ID(P_EN), ID(P_SRST_N), ID(P_BYPASS)); + st.ffP->connections_.at(ID::Q).replace(st.sigP, pm.module->addWire(NEW_ID, GetSize(st.sigP))); + } + + log(" clock: %s (%s)\n", log_signal(st.clock), "posedge"); + + if (st.ffA) + log(" \t ffA:%s\n", log_id(st.ffA)); + if (st.ffB) + log(" \t ffB:%s\n", log_id(st.ffB)); + if (st.ffD) + log(" \t ffD:%s\n", log_id(st.ffD)); + if (st.ffP) + log(" \t ffP:%s\n", log_id(st.ffP)); + } + log("\n"); + + SigSpec P = st.sigP; + if (GetSize(P) < 48) + P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); + cell->setPort(ID::P, P); + + pm.blacklist(cell); +} + +// For packing cascaded DSPs +void mchp_dsp_packC(mchp_dsp_CREG_pm &pm) +{ + auto &st = pm.st_mchp_dsp_packC; + + log_debug("Analysing %s.%s for MCHP DSP packing (REG_C).\n", log_id(pm.module), log_id(st.dsp)); + log_debug("ffC: %s\n", log_id(st.ffC, "--")); + + Cell *cell = st.dsp; + + if (st.clock != SigBit()) + { + cell->setPort(ID::CLK, st.clock); + + // same function as above, used for the last CREG we need to absorb + auto f = [&pm,cell](SigSpec &A, Cell* ff, IdString ceport, IdString rstport, IdString bypass) { + + // input/output ports + SigSpec D = ff->getPort(ID::D); + SigSpec Q = pm.sigmap(ff->getPort(ID::Q)); + if (!A.empty()) + A.replace(Q, D); + if (rstport != IdString()) { + if (ff->type.in(ID($sdff), ID($sdffe))) { + SigSpec srst = ff->getPort(ID::SRST); + bool rstpol_n = !ff->getParam(ID::SRST_POLARITY).as_bool(); + // active low sync rst + cell->setPort(rstport, rstpol_n ? srst : pm.module->Not(NEW_ID, srst)); + } else if (ff->type.in(ID($adff), ID($adffe))) { + SigSpec arst = ff->getPort(ID::ARST); + bool rstpol_n = !ff->getParam(ID::ARST_POLARITY).as_bool(); + // active low async rst + cell->setPort(rstport, rstpol_n ? arst : pm.module->Not(NEW_ID, arst)); + } else { + // active low async/sync rst + cell->setPort(rstport, State::S1); + } + } + if (ff->type.in(ID($dffe), ID($sdffe), ID($adffe))) { + SigSpec ce = ff->getPort(ID::EN); + bool cepol = ff->getParam(ID::EN_POLARITY).as_bool(); + // enables are all active high + cell->setPort(ceport, cepol ? ce : pm.module->Not(NEW_ID, ce)); + } else { + // enables are all active high + cell->setPort(ceport, State::S1); + } + + // bypass set to 0 + cell->setPort(bypass, State::S0); + + + for (auto c : Q.chunks()) { + auto it = c.wire->attributes.find(ID::init); + if (it == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset+c.width; i++) { + log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); + it->second[i] = State::Sx; + } + } + }; + + if (st.ffC) { + SigSpec C = cell->getPort(ID::C); + + if (st.ffC->type.in(ID($adff), ID($adffe))) { + f(C, st.ffC, ID(C_EN), ID(C_ARST_N), ID(C_BYPASS)); + } else { + f(C, st.ffC, ID(C_EN), ID(C_SRST_N), ID(C_BYPASS)); + } + pm.add_siguser(C, cell); + cell->setPort(ID::C, C); + } + + log(" clock: %s (%s)", log_signal(st.clock), "posedge"); + + if (st.ffC) + log(" ffC:%s", log_id(st.ffC)); + log("\n"); + } + + pm.blacklist(cell); +} + +struct MchpDspPass : public Pass { + MchpDspPass() : Pass("mchp_dsp", "MCHP: pack resources into DSPs") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" mchp_dsp [options] [selection]\n"); + log("\n"); + log("Pack input registers 'A', 'B', 'C', and 'D' (with optional enable/reset),\n"); + log("output register 'P' (with optional enable/reset), pre-adder and/or post-adder into\n"); + log("MCHP DSP resources.\n"); + log("\n"); + log("Multiply-accumulate operations using the post-adder with feedback on the 'C'\n"); + log("input will be folded into the DSP. In this scenario only, the 'C' input can be\n"); + log("used to override the current accumulation result with a new value. This will\n"); + log("be added to the multiplier result to form the next accumulation result.\n"); + log("\n"); + log("Use of the dedicated 'PCOUT' -> 'PCIN' cascade path is detected for 'P' -> 'C'\n"); + log("connections (optionally, where 'P' is right-shifted by 17-bits and used as an\n"); + log("input to the post-adder. This pattern is common for summing partial products to\n"); + log("implement wide multipliers). Cascade chains are limited to a mazimum length \n"); + log("of 24 cells, corresponding to PolarFire (pf) devices.\n"); + log("\n"); + log("This pass is a no-op if the scratchpad variable 'mchp_dsp.multonly' is set\n"); + log("to 1.\n"); + log("\n"); + log("\n"); + log(" -family {pf}\n"); + log(" select the family to target\n"); + log(" default: pf\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing MCHP_DSP pass (pack resources into DSPs).\n"); + + std::string family = "pf"; + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if ((args[argidx] == "-family") && argidx+1 < args.size()) { + family = args[++argidx]; + continue; + } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) { + + if (design->scratchpad_get_bool("mchp_dsp.multonly")) + continue; + + { + // For more details on PolarFire MACC_PA, consult + // the "PolarFire FPGA Macro Library Guide" + + // Main pattern matching step to capture a DSP cell. + // Match for pre-adder, post-adder, as well as + // registers 'A', 'B', 'D', and 'P'. Additionally, + // check for an accumulator pattern based on whether + // a post-adder and PREG are both present AND + // if PREG feeds into this post-adder. + mchp_dsp_pm pm(module, module->selected_cells()); + pm.run_mchp_dsp_pack(mchp_dsp_pack); + } + + // Separating out CREG packing is necessary since there + // is no guarantee that the cell ordering corresponds + // to the "expected" case (i.e. the order in which + // they appear in the source). There existed the possibility + // where a register got packed as a CREG into a + // downstream DSP that should have otherwise been a + // PREG of an upstream DSP that had not been visited + // yet + { + mchp_dsp_CREG_pm pm(module, module->selected_cells()); + pm.run_mchp_dsp_packC(mchp_dsp_packC); + } + + // Lastly, identify and utilise PCOUT -> PCIN chains + { + mchp_dsp_cascade_pm pm(module, module->selected_cells()); + pm.run_mchp_dsp_cascade(); + } + + } + } +} MchpDspPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/mchp_dsp.pmg b/passes/pmgen/mchp_dsp.pmg new file mode 100644 index 000000000..2580d64b4 --- /dev/null +++ b/passes/pmgen/mchp_dsp.pmg @@ -0,0 +1,440 @@ +// ISC License +// +// Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +// This file describes the main pattern matcher setup (of three total) that +// forms the `mchp_dsp` pass described in mchp_dsp.cc - version for +// DSP48A/DSP48A1 (Spartan 3A DSP, Spartan 6). +// At a high level, it works as follows: +// ( 1) Starting from a DSP cell. Capture DSP configurations as states +// ( 2) Match for pre-adder +// ( 3) Match for post-adder +// ( 4) Match register 'A', 'B', 'D', 'P' +// ( 5) If post-adder and PREG both present, check if PREG feeds into post-adder. +// This indicates an accumulator situation like the ASCII diagram below: +// +--------------------------------+ +// |_________ | +// | /-------\ +----+ | +// +----+ +-| post- |___|PREG|---+ 'P' +// |MULT|------ | adder | +----+ +// +----+ \-------/ + +pattern mchp_dsp_pack + +state clock +state sigA sigB sigC sigD sigP +state ffA ffB ffD ffP +state preAdderStatic postAdderStatic +state moveBtoA useFeedBack + +// static ports, used to detect dsp configuration +state bypassA bypassB bypassC bypassD bypassP +state bypassPASUB + +// Variables used for subpatterns +state argQ argD +udata allowAsync +udata dffD dffQ +udata dffclock +udata dff +udata u_preAdderStatic u_postAdderStatic +udata u_postAddAB +state postAddAB + +// (1) Starting from a DSP cell +match dsp + select dsp->type.in(\MACC_PA) +endmatch + +// detect existing signals connected to DSP +// detect configuration ports +code sigA sigB sigC sigD clock sigP + //helper function to remove unused bits + auto unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; + + //unextend to remove unused bits + sigA = unextend(port(dsp, \A)); + sigB = unextend(port(dsp, \B)); + + //update signals + sigC = port(dsp, \C, SigSpec()); + sigD = port(dsp, \D, SigSpec()); + + + SigSpec P = port(dsp, \P); + // Only care about bits that are used + int i; + for (i = GetSize(P)-1; i >= 0; i--) + if (nusers(P[i]) > 1) + break; + i++; + log_assert(nusers(P.extract_end(i)) <= 1); + // This sigP could have no users if downstream sinks (e.g. $add) is + // narrower than $mul result, for example + if (i == 0) + reject; + sigP = P.extract(0, i); + clock = port(dsp, \CLK, SigBit()); + +endcode + +// capture static configuration ports +code bypassA bypassB bypassC bypassD bypassPASUB bypassP + bypassA = port(dsp, \A_BYPASS, SigSpec()); + bypassB = port(dsp, \B_BYPASS, SigSpec()); + bypassC = port(dsp, \C_BYPASS, SigSpec()); + bypassD = port(dsp, \D_BYPASS, SigSpec()); + bypassPASUB = port(dsp, \PASUB_BYPASS, SigSpec()); + bypassP = port(dsp, \P_BYPASS, SigSpec()); +endcode + +// (2) Match for pre-adder +// +code sigA sigB sigD preAdderStatic moveBtoA + subpattern(preAddMatching); + preAdderStatic = u_preAdderStatic; + moveBtoA = false; + + if (preAdderStatic) { + + if (port(preAdderStatic, \Y) == sigA) + { + //used for packing + moveBtoA = true; + + // sigA should be the input to the multiplier without the preAdd. sigB and sigD should be + //the preAdd inputs. If our "A" input into the multiplier is from the preAdd (not sigA), then + // we basically swap it. + sigA = port(dsp, \B); + } + + // port B of preAdderStatic must be mapped to port D of DSP for subtraction + sigD = port(preAdderStatic, \B); + sigB = port(preAdderStatic, \A); + } +endcode + +// (3) Match for post-adder +// +code postAdderStatic sigP sigC + u_postAdderStatic = nullptr; + subpattern(postAddMatching); + postAdderStatic = u_postAdderStatic; + + if (postAdderStatic) { + //sigC will be whichever input to the postAdder that is NOT from the multiplier + // u_postAddAB is the input to the postAdder from the multiplier + sigC = port(postAdderStatic, u_postAddAB == \A ? \B : \A); + sigP = port(postAdderStatic, \Y); + } +endcode + + +// (4) Matching registers +// +// 'A' input for REG_A +code argQ bypassA sigA clock ffA + if (bypassA.is_fully_ones()){ + argQ = sigA; + allowAsync = false; + subpattern(in_dffe); + if (dff) { + ffA = dff; + clock = dffclock; + sigA = dffD; + } + } +endcode + +// 'B' input for REG_B +code argQ bypassB sigB clock ffB + if (bypassB.is_fully_ones()){ + argQ = sigB; + allowAsync = false; + subpattern(in_dffe); + if (dff) { + ffB = dff; + clock = dffclock; + sigB = dffD; + } + } +endcode + +// 'D' input for REG_D +code argQ bypassP sigD clock ffD + if (bypassD.is_fully_ones()){ + argQ = sigD; + allowAsync = true; + subpattern(in_dffe); + if (dff) { + ffD = dff; + clock = dffclock; + sigD = dffD; + } + } +endcode + +// 'P' output for REG_P +code argD ffP sigP clock bypassP + if (bypassP.is_fully_ones() && nusers(sigP) == 2) { + argD = sigP; + allowAsync = false; + subpattern(out_dffe); + if (dff) { + ffP = dff; + clock = dffclock; + sigP = dffQ; + } + } +endcode + +// (5) If post-adder and PREG both present, check if PREG feeds into post-adder via port C. +// This indicates an accumulator situation. Port C can be freed +// +--------------------------------+ +// |_________ | +// | /-------\ +----+ | +// +----+ +-| post- |___|PREG|---+ 'P' +// |MULT|------ | adder | +----+ +// +----+ \-------/ +code useFeedBack + useFeedBack = false; + if (postAdderStatic && ffP) { + if (sigC == sigP) { + useFeedBack = true; + } + } + +endcode + +// if any cells are absorbed, invoke the callback function +code + if (preAdderStatic || postAdderStatic) + accept; + if (ffA || ffB || ffD || ffP) + accept; +endcode + + +// ####################### +// Subpattern for matching against post-adder +// Match 'P' output that exclusively drives one of two inputs to an $add +// cell (post-adder). +// The other input to the adder is assumed to come in from the 'C' input + +subpattern postAddMatching +arg sigP + +match postAdd + + select postAdd->type.in($add, $sub) + select GetSize(port(postAdd, \Y)) <= 48 + + // AB is the port that connects MUL to ADD + choice AB {\A, \B} + select nusers(port(postAdd, AB)) == 2 + + // has one input coming from multiplier + index port(postAdd, AB)[0] === sigP[0] + filter GetSize(port(postAdd, AB)) >= GetSize(sigP) + filter port(postAdd, AB).extract(0, GetSize(sigP)) == sigP + // Check that remainder of AB is a sign- or zero-extension + filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(sigP[GetSize(sigP)-1], GetSize(port(postAdd, AB))-GetSize(sigP)) || port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(State::S0, GetSize(port(postAdd, AB))-GetSize(sigP)) + + set postAddAB AB + // optional +endmatch + +code + if (postAdd) + { + if (postAdd->type.in(ID($sub)) && postAddAB == \A) { + // if $sub, the multiplier output must match to $sub.B, otherwise no match + } else { + u_postAddAB = postAddAB; + u_postAdderStatic = postAdd; + } + + } +endcode + + +// ####################### +// Subpattern for matching against pre-adder +// support static PASUB only + +subpattern preAddMatching +arg sigA sigB sigD bypassB bypassD bypassPASUB + +code + u_preAdderStatic = nullptr; + + // Ensure that preAdder not already used + // Assume we can inspect port D to see if its all zeros. + if (!(sigD.empty() || sigD.is_fully_zero())) reject; + if (!bypassB.is_fully_ones()) reject; + if (!bypassD.is_fully_ones()) reject; + if (!bypassPASUB.is_fully_ones()) reject; +endcode + +match preAdd + + // can handle add or sub + select preAdd->type.in($add, $sub) + + // Output has to be 18 bits or less, and only has single fanout + select GetSize(port(preAdd, \Y)) <= 18 + select nusers(port(preAdd, \Y)) == 2 + + // Adder inputs must be 18 bits or less + select GetSize(port(preAdd, \A)) <= 18 + select GetSize(port(preAdd, \B)) <= 18 + + // Output feeds into one of multiplier input + filter port(preAdd, \Y) == sigB || port(preAdd, \Y) == sigA + + // optional +endmatch + +code + if (preAdd) + { + u_preAdderStatic = preAdd; + } +endcode + +// ####################### +// Subpattern for matching against input registers, based on knowledge of the +// 'Q' input. +subpattern in_dffe +arg argQ clock + +code + dff = nullptr; + if (argQ.empty()) + reject; + for (const auto &c : argQ.chunks()) { + // Abandon matches when 'Q' is a constant + if (!c.wire) + reject; + // Abandon matches when 'Q' has the keep attribute set + if (c.wire->get_bool_attribute(\keep)) + reject; + // Abandon matches when 'Q' has a non-zero init attribute set + Const init = c.wire->attributes.at(\init, Const()); + if (!init.empty()) + for (auto b : init.extract(c.offset, c.width)) + if (b != State::Sx && b != State::S0) + reject; + } +endcode + +match ff + // reg D has async rst + // reg A, B has sync rst + select ff->type.in($dff, $dffe, $sdff, $sdffe, $adff, $adffe) + // does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + + // it is possible that only part of a dff output matches argQ + slice offset GetSize(port(ff, \D)) + index port(ff, \Q)[offset] === argQ[0] + + // Check that the rest of argQ is present + filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) + filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + + // only consider async rst flops when flag is set + filter !ff->type.in($adff, $adffe) || allowAsync + + // clock must be consistent + filter clock == SigBit() || port(ff, \CLK) == clock +endmatch + +code argQ + // Check that reset value, if present, is fully 0. + bool noResetFlop = ff->type.in($dff, $dffe); + bool srstZero = ff->type.in($sdff, $sdffe) && param(ff, \SRST_VALUE).is_fully_zero(); + bool arstZero = ff->type.in($adff, $adffe) && param(ff, \ARST_VALUE).is_fully_zero(); + bool resetLegal = noResetFlop || srstZero || arstZero; + if (resetLegal) + { + SigSpec Q = port(ff, \Q); + dff = ff; + dffclock = port(ff, \CLK); + dffD = argQ; + SigSpec D = port(ff, \D); + argQ = Q; + dffD.replace(argQ, D); + } + +endcode +// ####################### + + +subpattern out_dffe +arg argD argQ clock + +code + dff = nullptr; + for (auto c : argD.chunks()) + // Abandon matches when 'D' has the keep attribute set + if (c.wire->get_bool_attribute(\keep)) + reject; +endcode + +match ff + select ff->type.in($dff, $dffe, $sdff, $sdffe) + // does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + + slice offset GetSize(port(ff, \D)) + index port(ff, \D)[offset] === argD[0] + + // Check that the rest of argD is present + filter GetSize(port(ff, \D)) >= offset + GetSize(argD) + filter port(ff, \D).extract(offset, GetSize(argD)) == argD + + filter clock == SigBit() || port(ff, \CLK) == clock +endmatch + +code argQ + SigSpec D = port(ff, \D); + SigSpec Q = port(ff, \Q); + argQ = argD; + argQ.replace(D, Q); + + // Abandon matches when 'Q' has a non-zero init attribute set + for (auto c : argQ.chunks()) { + Const init = c.wire->attributes.at(\init, Const()); + if (!init.empty()) + for (auto b : init.extract(c.offset, c.width)) + if (b != State::Sx && b != State::S0) + reject; + } + + dff = ff; + dffQ = argQ; + dffclock = port(ff, \CLK); +endcode diff --git a/passes/pmgen/mchp_dsp_CREG.pmg b/passes/pmgen/mchp_dsp_CREG.pmg new file mode 100644 index 000000000..8647f16a1 --- /dev/null +++ b/passes/pmgen/mchp_dsp_CREG.pmg @@ -0,0 +1,169 @@ +// ISC License +// +// Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +// This file describes the second of three pattern matcher setups that +// forms the `mchp_dsp` pass described in mchp_dsp.cc +// At a high level, it works as follows: +// (1) Starting from a DSP cell that (a) doesn't have a CREG already, +// and (b) uses the 'C' port +// (2) Match the driver of the 'C' input to a possible $dff cell (CREG) +// (attached to at most two $mux cells that implement clock-enable or +// reset functionality, using a subpattern discussed below) +// Notes: +// - Running CREG packing after mchp_dsp_pack is necessary since there is no +// guarantee that the cell ordering corresponds to the "expected" case (i.e. +// the order in which they appear in the source) thus the possiblity existed +// where a register got packed as a CREG into a downstream DSP, while it should +// have otherwise been a PREG of an upstream DSP that had not been visited. +// yet. +// - The reason this is separated out from the mchp_dsp.pmg file is +// for efficiency --- each *.pmg file creates a class of the same basename, +// which when constructed, creates a custom database tailored to the +// pattern(s) contained within. Since the pattern in this file must be +// executed after the pattern contained in mchp_dsp.pmg, it is necessary +// to reconstruct this database. Separating the two patterns into +// independent files causes two smaller, more specific, databases. + +pattern mchp_dsp_packC + +udata > unextend +state clock +state sigC sigP +state ffC + +// Variables used for subpatterns +state argQ argD +state ffoffset +udata dffD dffQ +udata dffclock +udata dff + +// (1) Starting from a DSP cell that (a) doesn't have a CREG already, +// and (b) uses the 'C' port +match dsp + select dsp->type.in(\MACC_PA) + select port(dsp, \C_BYPASS, SigSpec()).is_fully_ones() + select nusers(port(dsp, \C, SigSpec())) > 1 +endmatch + +code sigC sigP clock + //helper function to remove unused bits + unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; + sigC = unextend(port(dsp, \C, SigSpec())); + + SigSpec P = port(dsp, \P); + + // Only care about those bits that are used + int i; + for (i = GetSize(P)-1; i >= 0; i--) + if (nusers(P[i]) > 1) + break; + i++; + log_assert(nusers(P.extract_end(i)) <= 1); + sigP = P.extract(0, i); + + clock = port(dsp, \CLK, SigBit()); +endcode + +// (2) Match the driver of the 'C' input to a possible $dff cell (CREG) +// (attached to at most two $mux cells that implement clock-enable or +// reset functionality, using the in_dffe subpattern) +code argQ ffC sigC clock + argQ = sigC; + subpattern(in_dffe); + if (dff) { + ffC = dff; + clock = dffclock; + sigC = dffD; + } +endcode + +code + if (ffC) + accept; +endcode + +// ####################### + +// Subpattern for matching against input registers, based on knowledge of the +// 'Q' input. +subpattern in_dffe +arg argQ clock + +code + dff = nullptr; + if (argQ.empty()) + reject; + for (const auto &c : argQ.chunks()) { + // Abandon matches when 'Q' is a constant + if (!c.wire) + reject; + // Abandon matches when 'Q' has the keep attribute set + if (c.wire->get_bool_attribute(\keep)) + reject; + // Abandon matches when 'Q' has a non-zero init attribute set + // (not supported by DSP48E1) + Const init = c.wire->attributes.at(\init, Const()); + if (!init.empty()) + for (auto b : init.extract(c.offset, c.width)) + if (b != State::Sx && b != State::S0) + reject; + } +endcode + +match ff + select ff->type.in($dff, $dffe, $sdff, $sdffe, $adff, $adffe) + // does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + + slice offset GetSize(port(ff, \D)) + index port(ff, \Q)[offset] === argQ[0] + + // Check that the rest of argQ is present + filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) + filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ + + filter clock == SigBit() || port(ff, \CLK) == clock +endmatch + +code argQ + // Check that reset value, if present, is fully 0. + bool noResetFlop = ff->type.in($dff, $dffe); + bool srstZero = ff->type.in($sdff, $sdffe) && param(ff, \SRST_VALUE).is_fully_zero(); + bool arstZero = ff->type.in($adff, $adffe) && param(ff, \ARST_VALUE).is_fully_zero(); + bool resetLegal = noResetFlop || srstZero || arstZero; + if (resetLegal) + { + SigSpec Q = port(ff, \Q); + dff = ff; + dffclock = port(ff, \CLK); + dffD = argQ; + SigSpec D = port(ff, \D); + argQ = Q; + dffD.replace(argQ, D); + } + +endcode diff --git a/passes/pmgen/mchp_dsp_cascade.pmg b/passes/pmgen/mchp_dsp_cascade.pmg new file mode 100644 index 000000000..172dfb807 --- /dev/null +++ b/passes/pmgen/mchp_dsp_cascade.pmg @@ -0,0 +1,238 @@ +// ISC License +// +// Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +// This file describes the third of three pattern matcher setups that +// forms the `mchp_dsp` pass described in mchp_dsp.cc +// At a high level, it works as follows: +// (1) Starting from a DSP cell that +// (a) CDIN_FDBK_SEL is set to default "00" +// (b) doesn't already use the 'PCOUT' port +// (2) Match another DSP cell that +// (a) does not have the CREG enabled, +// (b) 'C' port is driven by the 'P' output of the previous DSP cell +// (c) has its 'PCIN' port unused +// (3) Recursively go to (2) until no more matches possible, keeping track +// of the longest possible chain found +// (4) The longest chain is then divided into chunks of no more than +// MAX_DSP_CASCADE in length (to prevent long cascades that exceed the +// height of a DSP column) with each DSP in each chunk being rewritten +// to use [ABP]COUT -> [ABP]CIN cascading as appropriate + +pattern mchp_dsp_cascade + +udata > unextend +udata >> chain longest_chain +udata > visited +state next +state clock + +// Variables used for subpatterns +state argQ argD +state ffoffset +udata dffD dffQ +udata dffclock +udata dff + +// Maximum of 24 cascaded blocks +code +#define MAX_DSP_CASCADE 24 +endcode + +// NOTE: Chain vector +// +--------+ +--------+ +// | first |----> | next | ----> ... +// +--------+ +--------+ +// first.COUT cascades to next.CIN, so on and so forth + +// Helper function to remove unused bits +code + unextend = [](const SigSpec &sig) { + int i; + for (i = GetSize(sig)-1; i > 0; i--) + if (sig[i] != sig[i-1]) + break; + // Do not remove non-const sign bit + if (sig[i].wire) + ++i; + return sig.extract(0, i); + }; +endcode + +// (1) Starting from a DSP cell that +// (a) CDIN_FDBK_SEL is set to default "00" +// (b) doesn't already use the 'PCOUT' port +match first + select first->type.in(\MACC_PA) && port(first, \CDIN_FDBK_SEL, Const(0, 2)) == Const::from_string("00") + select nusers(port(first, \CDOUT, SigSpec())) <= 1 +endmatch + +// (4) The longest chain is then divided into chunks of no more than +// MAX_DSP_CASCADE in length (to prevent long cascades that exceed the +// height of a DSP column) with each DSP in each chunk being rewritten +// to use [ABP]COUT -> [ABP]CIN cascading as appropriate +code + visited.clear(); + visited.insert(first); + + longest_chain.clear(); + chain.emplace_back(first, -1); + subpattern(tail); +finally + + // longest cascade chain has been found with DSP "first" being the head of the chain + // do some post processing + + chain.pop_back(); + visited.clear(); + log_assert(chain.empty()); + + if (GetSize(longest_chain) > 1) { + Cell *dsp = std::get<0>(longest_chain.front()); + + Cell *dsp_pcin; + int SHIFT = -1; + for (int i = 1; i < GetSize(longest_chain); i++) { + log_assert(dsp->type.in(\MACC_PA)); + + std::tie(dsp_pcin,SHIFT) = longest_chain[i]; + + // Chain length exceeds the maximum cascade length, must split it up + if (i % MAX_DSP_CASCADE > 0) { + Wire *cascade = module->addWire(NEW_ID, 48); + + // zero port C and move wire to cascade + dsp_pcin->setPort(ID(C), Const(0, 48)); + dsp_pcin->setPort(ID(CDIN), cascade); + dsp->setPort(ID(CDOUT), cascade); + + // Configure wire to cascade the dsps + add_siguser(cascade, dsp_pcin); + add_siguser(cascade, dsp); + + // configure mux to use cascade for signal E + SigSpec cdin_fdbk_sel = port(dsp_pcin, \CDIN_FDBK_SEL, Const(0, 2)); + cdin_fdbk_sel[1] = State::S1; + dsp_pcin->setPort(\CDIN_FDBK_SEL, cdin_fdbk_sel); + + // check if shifting is required for wide multiplier implmentation + if (SHIFT == 17) + { + dsp_pcin->setPort(\ARSHFT17, State::S1); + } + + + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + + } else { + log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); + } + + dsp = dsp_pcin; + } + + accept; + } +endcode + +// ------------------------------------------------------------------ + +subpattern tail +arg first +arg next + +// (2) Match another DSP cell that +// (a) does not have the CREG enabled, +// (b) 'C' port is driven by the 'P' output of the previous DSP cell +// (c) has its 'PCIN' port unused +match nextP + // find candidates where nextP.C port is driven (maybe partially) by chain's tail DSP.P port + // and with no registers in between (since cascade path cannot be pipelined) + + // reg C must not be used + select port(nextP, \C_BYPASS, SigSpec()).is_fully_ones() + + // must be same DSP type + select nextP->type.in(\MACC_PA) + + // port C should be driven by something + select nusers(port(nextP, \C, SigSpec())) > 1 + + // CIN must be unused + select nusers(port(nextP, \PCIN, SigSpec())) == 0 + + // should not have internal feedback connection + select port(nextP, \CDIN_FDBK_SEL, SigSpec()).is_fully_zero() + + // SHIFT should be unused + select port(nextP, \ARSHFT17_BYPASS).is_fully_ones() + select port(nextP, \ARSHFT17).is_fully_zero() + select nusers(port(nextP, \ARSHFT17, SigSpec())) == 0 + + // current DSP cell can be cascaded with the back of the cascade chain + // index port(nextP, \C)[0] === port(std::get<0>(chain.back()), \P)[0] || port(nextP, \C)[0] === port(std::get<0>(chain.back()), \P)[17] + filter port(nextP, \C)[0] == port(std::get<0>(chain.back()), \P)[0] || port(nextP, \C)[0] == port(std::get<0>(chain.back()), \P)[17] + + // semioptional + + optional +endmatch + +code next + next = nextP; + + // keep DSP type consistent in the chain + // currently since we only have one type anyways, this line is always false + if (next && next->type != first->type) reject; + + // break infinite recursion when there's a combinational loop + if (visited.count(next) > 0) reject; + +endcode + +// (3) Recursively go to (2) until no more matches possible, recording the +// longest possible chain +code + if (next) { + SigSpec driver_sigP = port(std::get<0>(chain.back()), \P); + int shift = 0; + if (port(next, \C)[0] == port(std::get<0>(chain.back()), \P)[17]) shift = 17; + + chain.emplace_back(next, shift); + visited.insert(next); + + SigSpec sigC = unextend(port(next, \C)); + + // Make sure driverDSP.P === DSP.C + if (GetSize(sigC) + shift <= GetSize(driver_sigP) && driver_sigP.extract(shift, GetSize(sigC)) == sigC) + { + subpattern(tail); + } + + + } else { + if (GetSize(chain) > GetSize(longest_chain)) + longest_chain = chain; + } +finally + if (next) + { + visited.erase(next); + chain.pop_back(); + } + + +endcode \ No newline at end of file diff --git a/techlibs/mchp/LSRAM.txt b/techlibs/mchp/LSRAM.txt new file mode 100644 index 000000000..abd274eec --- /dev/null +++ b/techlibs/mchp/LSRAM.txt @@ -0,0 +1,191 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + + + +# LSRAM true dual-port +ram block $__LSRAM_TDP_ { + + # Cost of a given cell is assumed to be: + # (cost-widthscale) + [widthscale * (used_bits/14)] + cost 129; + + # INIT is supported + init any; + + # port A and port B are allowed to have different widths, but they MUST have + # WIDTH values of the same set. + # Example: Port A has a Data Width of 1. Then Port B's Data Width must be either + # 1, 2, 4, 8, or 16 (both values are in the 'WIDTH_1' set). + # WIDTH_1 = {1, 2, 4, 8, 16} + # WIDTH_2 = {5, 10, 20} + + # "byte" specifies how many data bits correspond to one write enable bit. + # "byte" must be larger than width, or width must be a multipler of "byte" + # if "byte" > WIDTH, a single enable wire is inferred + # otherwise, WIDTH/byte number of enable wires are inferred + # + # WIDTH = {1, 2, 4, 5, 8, 10} requires 1 enable wire + # WIDTH = {16, 20} requires 2 enable wire + + option "WIDTH_CONFIG" "REGULAR" { + + # Data-Width | Address bits + # 1 | 14 + # 2 | 13 + # 4 | 12 + # 8 | 11 + # 16 | 10 + + # 14 address bits + abits 14; + + widths 1 2 4 8 16 per_port; + byte 8; + } + option "WIDTH_CONFIG" "ALIGN" { + + # Data-Width | Address bits + # 5 | 12 + # 10 | 11 + # 20 | 10 + + # Quick "hack" to fix address bit alignment by setting address bits to 12. + # If abits=14, tool will think there are 14 bits for width=5, 13 bits for width=10, 12 bits for width=20 + # THe LSRAM_map.v file detects if this option is being used, and adjusts the address port alignments accordingly. + abits 12; + + widths 5 10 20 per_port; + byte 10; + } + + + + port srsw "A" "B" { + + # read & write width must be same + width tied; + + # clock polarity is rising + clock posedge; + + # A/B read-enable + rden; + + + # initial value of read port data (not supported) + rdinit none; + + # write modes (_WMODE) + # 1. Simple Write: read-data port holds prev value (similar to "NO_CHANGE" for RAMB18E1) + # 2. Feed-through: read-data port takes new write value (similar to "WRITE_FIRST" for RAMB18E1) + # 3. Read-Before-Write: read-data port holds old value while being written (similar to "READ_FIRST" for RAMB18E1) + + portoption "WRITE_MODE" "NO_CHANGE" { + + # Read-write interaction + rdwr no_change; + + # Write transparency: + # For write ports, define behaviour when another synchronous read port + # reads from the same memory cell that said write port is writing to at the same time. + wrtrans all old; + } + portoption "WRITE_MODE" "WRITE_FIRST" { + # bits corresponding to high A/B_WEN are updated + rdwr new_only; + wrtrans all new; + } + portoption "WRITE_MODE" "READ_FIRST" { + rdwr old; + + wrtrans all old; + } + + # generate params to indicate if read or write is used for each port + optional_rw; + } +} + +# two-port configuration +ram block $__LSRAM_SDP_ { + + # since two-port configuration is dedicated for wide-read/write, + # we want to prioritize this configuration over TDP to avoid tool picking multiple TDP RAMs + # inplace of a single SDP RAM for wide read/write. This means the cost of a single SDP should + # be less than 2 TDP. + cost 129; + init any; + + option "WIDTH_CONFIG" "REGULAR" { + + # Data-Width | Address bits + # 1 | 14 + # 2 | 13 + # 4 | 12 + # 8 | 11 + # 16 | 10 + # 32 | 9 + + abits 14; + + widths 1 2 4 8 16 32 per_port; + + # width = 32, byte-write size is 8, ignore other widths + byte 8; + + } + option "WIDTH_CONFIG" "ALIGN" { + + # Data-Width | Address bits + # 5 | 12 + # 10 | 11 + # 20 | 10 + # 40 | 9 + + # Same trick as TSP RAM for alignment + abits 12; + widths 5 10 20 40 per_port; + byte 10; + } + + port sw "W" { + + # only consider wide write + + option "WIDTH_CONFIG" "REGULAR" width 32; + option "WIDTH_CONFIG" "ALIGN" width 40; + + clock posedge; + + # only simple write supported for two-port mode + wrtrans all old; + + optional; + } + port sr "R" { + + option "WIDTH_CONFIG" "REGULAR" width 32; + option "WIDTH_CONFIG" "ALIGN" width 40; + + + clock posedge; + rden; + rdinit none; + optional; + } +} diff --git a/techlibs/mchp/LSRAM_map.v b/techlibs/mchp/LSRAM_map.v new file mode 100644 index 000000000..6eaf2f459 --- /dev/null +++ b/techlibs/mchp/LSRAM_map.v @@ -0,0 +1,323 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +// See document PolarFire Family Fabric User Guide +// section 4.1 for port list. + + +//LSRAM true dual-port +module $__LSRAM_TDP_ (...); + +parameter INIT = 0; +parameter ADDR_BITS = 14; + +parameter OPTION_WIDTH_CONFIG = "A"; + +parameter PORT_A_WIDTH = 1; +parameter PORT_A_WR_EN_WIDTH = 1; +parameter PORT_A_RD_USED = 0; +parameter PORT_A_WR_USED = 0; +parameter PORT_A_OPTION_WRITE_MODE = "NO_CHANGE"; + +parameter PORT_B_WIDTH = 1; +parameter PORT_B_WR_EN_WIDTH = 1; +parameter PORT_B_RD_USED = 0; +parameter PORT_B_WR_USED = 0; +parameter PORT_B_OPTION_WRITE_MODE = "NO_CHANGE"; + + +input PORT_A_CLK; +input PORT_A_RD_EN; +input [ADDR_BITS-1:0] PORT_A_ADDR; +input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA; +input [PORT_A_WR_EN_WIDTH-1:0] PORT_A_WR_EN; +output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA; + + +input PORT_B_CLK; +input PORT_B_RD_EN; +input [ADDR_BITS-1:0] PORT_B_ADDR; +input [PORT_B_WIDTH-1:0] PORT_B_WR_DATA; +input [PORT_B_WR_EN_WIDTH-1:0] PORT_B_WR_EN; +output [PORT_B_WIDTH-1:0] PORT_B_RD_DATA; + + +`include "brams_defs.vh" + +// address wires +wire [ADDR_BITS-1:0] A_address; +wire [ADDR_BITS-1:0] B_address; +assign A_address = (OPTION_WIDTH_CONFIG == "REGULAR") ? PORT_A_ADDR : {PORT_A_ADDR, 2'b00}; +assign B_address = (OPTION_WIDTH_CONFIG == "REGULAR") ? PORT_B_ADDR : {PORT_B_ADDR, 2'b00}; + +// if port is not used, set block sel to 0 to disable it (read-data output is set to 0) +parameter PORT_A_RD_USED = 0; +parameter PORT_A_WR_USED = 0; +wire [2:0] A_BLK_SEL = (PORT_A_RD_USED == 1 || PORT_A_WR_USED == 1) ? 3'b111 : 3'b000; +wire [2:0] B_BLK_SEL = (PORT_B_RD_USED == 1 || PORT_B_WR_USED == 1) ? 3'b111 : 3'b000; + +// wires for write data +generate + wire [19:0] A_write_data; + wire [19:0] B_write_data; + if (PORT_A_WIDTH == 16) begin + assign A_write_data[7:0] = PORT_A_WR_DATA[7:0]; + assign A_write_data[17:10] = PORT_A_WR_DATA[15:8]; + assign A_write_data[9:8] = 2'b0; + assign A_write_data[19:18] = 2'b0; + end else begin + assign A_write_data[PORT_A_WIDTH-1:0] = PORT_A_WR_DATA; + end + + if (PORT_B_WIDTH == 16) begin + assign B_write_data[7:0] = PORT_B_WR_DATA[7:0]; + assign B_write_data[17:10] = PORT_B_WR_DATA[15:8]; + assign B_write_data[9:8] = 2'b0; + assign B_write_data[19:18] = 2'b0; + end else begin + assign B_write_data[PORT_B_WIDTH-1:0] = PORT_B_WR_DATA; + end +endgenerate + +// wires for read data +wire [19:0] A_read_data; +assign PORT_A_RD_DATA = A_read_data[PORT_A_WIDTH-1:0]; +wire [19:0] B_read_data; +assign PORT_B_RD_DATA = B_read_data[PORT_B_WIDTH-1:0]; + +// byte-write enables +wire [1:0] A_write_EN = (PORT_A_WR_EN_WIDTH == 1) ? {1'b0, PORT_A_WR_EN} : PORT_A_WR_EN; +wire [1:0] B_write_EN = (PORT_B_WR_EN_WIDTH == 1) ? {1'b0, PORT_B_WR_EN} : PORT_B_WR_EN; + +// port width +wire [2:0] A_width = (PORT_A_WIDTH == 1) ? 3'b000 : + (PORT_A_WIDTH == 2) ? 3'b001 : + (PORT_A_WIDTH == 4 || PORT_A_WIDTH == 5) ? 3'b010 : + (PORT_A_WIDTH == 8 || PORT_A_WIDTH == 10) ? 3'b011 : 3'b100; +wire [2:0] B_width = (PORT_B_WIDTH == 1) ? 3'b000 : + (PORT_B_WIDTH == 2) ? 3'b001 : + (PORT_B_WIDTH == 4 || PORT_B_WIDTH == 5) ? 3'b010 : + (PORT_B_WIDTH == 8 || PORT_B_WIDTH == 10) ? 3'b011 : 3'b100; + +// write modes +wire [1:0] A_write_mode = PORT_A_OPTION_WRITE_MODE == "NO_CHANGE" ? 2'b00 : + PORT_A_OPTION_WRITE_MODE == "WRITE_FIRST" ? 2'b01 : 2'b10; +wire [1:0] B_write_mode = PORT_B_OPTION_WRITE_MODE == "NO_CHANGE" ? 2'b00 : + PORT_B_OPTION_WRITE_MODE == "WRITE_FIRST" ? 2'b01 : 2'b10; + +RAM1K20 #( + `PARAMS_INIT_LSRAM +) _TECHMAP_REPLACE_ ( + + // port A + .A_ADDR(A_address), + .A_BLK_EN(A_BLK_SEL), + .A_CLK(PORT_A_CLK), + .A_DIN(A_write_data), + .A_DOUT(A_read_data), + .A_WEN(A_write_EN), + .A_REN(PORT_A_RD_EN), + .A_WIDTH(A_width), + .A_WMODE(A_write_mode), + .A_BYPASS(1'b1), + .A_DOUT_EN(1'b1), + .A_DOUT_SRST_N(1'b1), + .A_DOUT_ARST_N(1'b1), + + // port B + .B_ADDR(B_address), + .B_BLK_EN(B_BLK_SEL), + .B_CLK(PORT_B_CLK), + .B_DIN(B_write_data), + .B_DOUT(B_read_data), + .B_WEN(B_write_EN), + .B_REN(PORT_B_RD_EN), + .B_WIDTH(B_width), + .B_WMODE(B_write_mode), + .B_BYPASS(1'b1), + .B_DOUT_EN(1'b1), + .B_DOUT_SRST_N(1'b1), + .B_DOUT_ARST_N(1'b1), + + // Disable ECC for TDP + .ECC_EN(1'b0), + .ECC_BYPASS(1'b1), + .BUSY_FB(1'b0) + +); + +endmodule + +// single dual port configuration +module $__LSRAM_SDP_ (...); + +parameter INIT = 0; +parameter OPTION_WIDTH_CONFIG = "REGULAR"; +parameter ADDR_BITS = 14; + +parameter PORT_W_WIDTH = 1; +parameter PORT_W_WR_EN_WIDTH = 4; +parameter PORT_W_USED = 1; + +parameter PORT_R_WIDTH = 1; +parameter PORT_R_USED = 0; + +input PORT_W_CLK; +input [ADDR_BITS-1:0] PORT_W_ADDR; +input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA; +input [PORT_W_WR_EN_WIDTH-1:0] PORT_W_WR_EN; + +input PORT_R_CLK; +input PORT_R_RD_EN; +input [ADDR_BITS-1:0] PORT_R_ADDR; +output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA; +input PORT_R_RD_SRST; + +`include "brams_defs.vh" + + +// address wires +wire [ADDR_BITS-1:0] A_address; +wire [ADDR_BITS-1:0] B_address; +assign A_address = (OPTION_WIDTH_CONFIG == "REGULAR") ? PORT_R_ADDR : {PORT_R_ADDR, 2'b00}; +assign B_address = (OPTION_WIDTH_CONFIG == "REGULAR") ? PORT_W_ADDR : {PORT_W_ADDR, 2'b00}; + +// if port is not used, set block sel to 0 to disable it (read-data output is set to 0) +// port A is for read, port B for write +parameter PORT_W_USED = 0; +parameter PORT_R_USED = 0; +wire [2:0] A_BLK_SEL = (PORT_R_USED == 1) ? 3'b111 : 3'b000; +wire [2:0] B_BLK_SEL = (PORT_W_USED == 1) ? 3'b111 : 3'b000; + +// read/write data & write enables +// Currently support only wide write, width = {32, 40} +generate + wire [19:0] A_write_data; + wire [19:0] B_write_data; + wire [1:0] A_write_EN; + wire [1:0] B_write_EN; + + // write port (A provides MSB) + if (PORT_W_WIDTH == 32) begin + + assign B_write_data[3:0] = PORT_W_WR_DATA[3:0]; + assign B_write_data[8:5] = PORT_W_WR_DATA[7:4]; + assign B_write_data[13:10] = PORT_W_WR_DATA[11:8]; + assign B_write_data[18:15] = PORT_W_WR_DATA[15:12]; + assign B_write_data[4] = 1'b0; + assign B_write_data[9] = 1'b0; + assign B_write_data[14] = 1'b0; + assign B_write_data[19] = 1'b0; + + assign A_write_data[3:0] = PORT_W_WR_DATA[19:16]; + assign A_write_data[8:5] = PORT_W_WR_DATA[23:20]; + assign A_write_data[13:10] = PORT_W_WR_DATA[27:24]; + assign A_write_data[18:15] = PORT_W_WR_DATA[31:28]; + assign A_write_data[4] = 1'b0; + assign A_write_data[9] = 1'b0; + assign A_write_data[14] = 1'b0; + assign A_write_data[19] = 1'b0; + + end else if (PORT_W_WIDTH == 40) begin + assign B_write_data = PORT_W_WR_DATA[19:0]; + assign A_write_data = PORT_W_WR_DATA[39:20]; + end + + // byte-write enables + assign A_write_EN = PORT_W_WR_EN[1:0]; + assign B_write_EN = PORT_W_WR_EN[3:2]; + + // read ports (A provides MSB) + wire [19:0] A_read_data; + wire [19:0] B_read_data; + if (PORT_R_WIDTH == 32) begin + assign PORT_R_RD_DATA[3:0] = B_read_data[3:0]; + assign PORT_R_RD_DATA[8:5] = B_read_data[7:4]; + assign PORT_R_RD_DATA[13:10] = B_read_data[11:8]; + assign PORT_R_RD_DATA[18:15] = B_read_data[15:12]; + + assign PORT_R_RD_DATA[19:16] = A_read_data[3:0]; + assign PORT_R_RD_DATA[23:20] = A_read_data[8:5]; + assign PORT_R_RD_DATA[27:24] = A_read_data[13:10]; + assign PORT_R_RD_DATA[31:28] = A_read_data[18:15]; + end else if (PORT_R_WIDTH == 40) begin + assign PORT_R_RD_DATA[19:0] = B_read_data[19:0]; + assign PORT_R_RD_DATA[39:20] = A_read_data[19:0]; + end + +endgenerate + +// port width +wire [2:0] A_width = (PORT_R_WIDTH == 1) ? 3'b000 : + (PORT_R_WIDTH == 2) ? 3'b001 : + (PORT_R_WIDTH == 4 || PORT_R_WIDTH == 5) ? 3'b010 : + (PORT_R_WIDTH == 8 || PORT_R_WIDTH == 10) ? 3'b011 : + (PORT_R_WIDTH == 16 || PORT_R_WIDTH == 20) ? 3'b100 : 3'b101; +wire [2:0] B_width = (PORT_W_WIDTH == 1) ? 3'b000 : + (PORT_W_WIDTH == 2) ? 3'b001 : + (PORT_W_WIDTH == 4 || PORT_W_WIDTH == 5) ? 3'b010 : + (PORT_W_WIDTH == 8 || PORT_W_WIDTH == 10) ? 3'b011 : + (PORT_W_WIDTH == 16 || PORT_W_WIDTH == 20) ? 3'b100 : 3'b101; + +// write modes +wire [1:0] A_write_mode = 2'b00; +wire [1:0] B_write_mode = 2'b00; + +RAM1K20 #( + `PARAMS_INIT_LSRAM +) _TECHMAP_REPLACE_ ( + // port A - read + .A_ADDR(A_address), + .A_BLK_EN(A_BLK_SEL), + .A_CLK(PORT_R_CLK), + .A_DIN(A_write_data), + .A_DOUT(A_read_data), + .A_WEN(A_write_EN), + .A_REN(PORT_R_RD_EN), + .A_WIDTH(A_width), + .A_WMODE(A_write_mode), + .A_BYPASS(1'b1), + .A_DOUT_EN(1'b1), + .A_DOUT_SRST_N(1'b1), + .A_DOUT_ARST_N(1'b1), + + // port B - write + .B_ADDR(B_address), + .B_BLK_EN(B_BLK_SEL), + .B_CLK(PORT_W_CLK), + .B_DIN(B_write_data), + .B_DOUT(B_read_data), + .B_WEN(B_write_EN), + .B_REN(PORT_R_RD_EN), + .B_WIDTH(B_width), + .B_WMODE(B_write_mode), + .B_BYPASS(1'b1), + .B_DOUT_EN(1'b1), + .B_DOUT_SRST_N(1'b1), + .B_DOUT_ARST_N(1'b1), + + // Disable ECC for SDP + .ECC_EN(1'b0), + .ECC_BYPASS(1'b1), + + .BUSY_FB(1'b0) + +); + + +endmodule diff --git a/techlibs/mchp/Makefile.inc b/techlibs/mchp/Makefile.inc new file mode 100644 index 000000000..a716caa9f --- /dev/null +++ b/techlibs/mchp/Makefile.inc @@ -0,0 +1,31 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + + +OBJS += techlibs/mchp/synth_mchp.o +OBJS += techlibs/mchp/mchp_dffopt.o + +$(eval $(call add_share_file,share/mchp,techlibs/mchp/arith_map.v)) +$(eval $(call add_share_file,share/mchp,techlibs/mchp/cells_map.v)) +$(eval $(call add_share_file,share/mchp,techlibs/mchp/cells_sim.v)) +$(eval $(call add_share_file,share/mchp,techlibs/mchp/pf_dsp_map.v)) + +$(eval $(call add_share_file,share/mchp,techlibs/mchp/brams_defs.vh)) +$(eval $(call add_share_file,share/mchp,techlibs/mchp/LSRAM_map.v)) +$(eval $(call add_share_file,share/mchp,techlibs/mchp/LSRAM.txt)) +$(eval $(call add_share_file,share/mchp,techlibs/mchp/uSRAM_map.v)) +$(eval $(call add_share_file,share/mchp,techlibs/mchp/uSRAM.txt)) diff --git a/techlibs/mchp/arith_map.v b/techlibs/mchp/arith_map.v new file mode 100644 index 000000000..d6c289c92 --- /dev/null +++ b/techlibs/mchp/arith_map.v @@ -0,0 +1,105 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +// Based on Macro Library for PolarFire https://coredocs.s3.amazonaws.com/Libero/2021_2/Tool/pf_mlg.pdf +// NOTE: prefix module names with \$__ so that mapping prioritizes these cells over internal Yosys cells + + +(* techmap_celltype = "$_MUX4_" *) +module \$__mchp_MUX4_ (A, B, C, D, S, T, Y); + input A, B, C, D, S, T; + output Y; + MX4 _TECHMAP_REPLACE_.MUX4(.D3(D), .D2(C), .D1(B), .D0(A), .S1(T), .S0(S), .Y(Y)); + +endmodule + + +(* techmap_celltype = "$reduce_xor" *) +module \$__mchp_XOR8_ (A, Y); + parameter A_SIGNED = 0; + parameter A_WIDTH = 0; + parameter Y_WIDTH = 0; + + input [A_WIDTH-1:0] A; + output [Y_WIDTH-1:0] Y; + + // check if mapping should proceed + generate + if (A_WIDTH != 8 || A_SIGNED || Y_WIDTH != 1) begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate + + + XOR8 _TECHMAP_REPLACE_.XOR8 (.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .F(A[5]), .G(A[6]), .H(A[7]), .Y(Y)); + + +endmodule + +(* techmap_celltype = "$alu" *) +module \$__SF2_ALU (A, B, CI, BI, X, Y, CO); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] X, Y; + + input CI, BI; + (* force_downto *) + output [Y_WIDTH-1:0] CO; + + wire _TECHMAP_FAIL_ = Y_WIDTH <= 2; + + (* force_downto *) + wire [Y_WIDTH-1:0] AA, BB; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(AA)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(BB)); + + (* force_downto *) + wire [Y_WIDTH-1:0] C = {CO, CI}; + + genvar i; + generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice + ARI1 #( + // See section 1.4 of PolarFire Macro Library + + // G = F1 = A[i] & (B[i]^BI) + // Y = F0 = A[i]^B[i]^BI + // P = Y + // ADCB + .INIT(20'b 01_11_0010_1000_1001_0110) + ) carry ( + .A(1'b0), + .B(AA[i]), + .C(BB[i]), + .D(BI), + .FCI(C[i]), + .Y(X[i]), + .S(Y[i]), + .FCO(CO[i]) + ); + end endgenerate +endmodule + diff --git a/techlibs/mchp/brams_defs.vh b/techlibs/mchp/brams_defs.vh new file mode 100644 index 000000000..157945fdb --- /dev/null +++ b/techlibs/mchp/brams_defs.vh @@ -0,0 +1,48 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +`define PARAMS_INIT_LSRAM \ + .INIT0(slice_init_LSRAM(00)), \ + .INIT1(slice_init_LSRAM(01)), \ + .INIT2(slice_init_LSRAM(02)), \ + .INIT3(slice_init_LSRAM(03)), \ + .INIT4(slice_init_LSRAM(04)), \ + .INIT5(slice_init_LSRAM(05)), \ + .INIT6(slice_init_LSRAM(06)), \ + .INIT7(slice_init_LSRAM(07)), \ + .INIT8(slice_init_LSRAM(08)), \ + .INIT9(slice_init_LSRAM(09)), \ + .INIT10(slice_init_LSRAM(10)), \ + .INIT11(slice_init_LSRAM(11)), \ + .INIT12(slice_init_LSRAM(12)), \ + .INIT13(slice_init_LSRAM(13)), \ + .INIT14(slice_init_LSRAM(14)), \ + .INIT15(slice_init_LSRAM(15)), \ + .INIT16(slice_init_LSRAM(16)), \ + .INIT17(slice_init_LSRAM(17)), \ + .INIT18(slice_init_LSRAM(18)), \ + .INIT19(slice_init_LSRAM(19)) + +// Helper function for initializing the LSRAM +function [1023:0] slice_init_LSRAM; + input integer slice_idx; + integer i; + for (i = 0; i < 1024; i = i + 1) + slice_init_LSRAM[i] = INIT[(slice_idx * 1024 + i)]; +endfunction + diff --git a/techlibs/mchp/cells_map.v b/techlibs/mchp/cells_map.v new file mode 100644 index 000000000..f52018aef --- /dev/null +++ b/techlibs/mchp/cells_map.v @@ -0,0 +1,104 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +// DFFs +module \$_DFFE_PN0P_ (input D, C, R, E, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(E), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +module \$_DFFE_PN1P_ (input D, C, R, E, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(E), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule + +// for sync set/reset registers, we can pass them into ABC9. So we need to follow the simplification idiom +// and map to intermediate cell types +module \$_SDFFCE_PN0P_ (input D, C, R, E, output Q); + MCHP_SYNC_RESET_DFF _TECHMAP_REPLACE_ (.D(D), .CLK(C), .Reset(R), .En(E), .Q(Q)); +endmodule + +module \$_SDFFCE_PN1P_ (input D, C, R, E, output Q); + MCHP_SYNC_SET_DFF _TECHMAP_REPLACE_ (.D(D), .CLK(C), .Set(R), .En(E), .Q(Q)); +endmodule + + +// LATCHES + +module \$_DLATCH_PN0_ (input D, R, E, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(E), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b1), .Q(Q)); +endmodule + +module \$_DLATCH_PN1_ (input D, R, E, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(E), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b1), .Q(Q)); +endmodule + +module \$_DLATCH_P_ (input D, E, output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(E), .EN(1'b1), .ALn(1'b1), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b1), .Q(Q)); +endmodule + +// map intermediate flops to SLE +`ifdef FINAL_MAP +module MCHP_SYNC_SET_DFF( + input D, + input CLK, + input Set, + input En, + output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(CLK), .EN(En), .ALn(1'b1), .ADn(1'b0), .SLn(Set), .SD(1'b1), .LAT(1'b0), .Q(Q)); +endmodule + +module MCHP_SYNC_RESET_DFF( + input D, + input CLK, + input Reset, + input En, + output Q); + SLE _TECHMAP_REPLACE_ (.D(D), .CLK(CLK), .EN(En), .ALn(1'b1), .ADn(1'b0), .SLn(Reset), .SD(1'b0), .LAT(1'b0), .Q(Q)); +endmodule +`endif + + +// LUT + +`ifndef NO_LUT +module \$lut (A, Y); + parameter WIDTH = 0; + parameter LUT = 0; + + (* force_downto *) + input [WIDTH-1:0] A; + output Y; + + generate + if (WIDTH == 1) begin + CFG1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0])); + end else + if (WIDTH == 2) begin + CFG2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1])); + end else + if (WIDTH == 3) begin + CFG3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1]), .C(A[2])); + end else + if (WIDTH == 4) begin + CFG4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Y(Y), .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3])); + end else begin + wire _TECHMAP_FAIL_ = 1; + end + endgenerate +endmodule +`endif + diff --git a/techlibs/mchp/cells_sim.v b/techlibs/mchp/cells_sim.v new file mode 100644 index 000000000..a7a96d86a --- /dev/null +++ b/techlibs/mchp/cells_sim.v @@ -0,0 +1,849 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +// Macro Library for PolarFire https://coredocs.s3.amazonaws.com/Libero/2021_2/Tool/pf_mlg.pdf + +module AND2 ( + input A, B, + output Y +); + assign Y = A & B; +endmodule + +module AND3 ( + input A, B, C, + output Y +); + assign Y = A & B & C; +endmodule + +module AND4 ( + input A, B, C, D, + output Y +); + assign Y = A & B & C & D; +endmodule + +(* abc9_lut=1 *) +module CFG1 ( + output Y, + input A +); + parameter [1:0] INIT = 2'h0; + assign Y = INIT >> A; + specify + (A => Y) = 127; + endspecify +endmodule + +(* abc9_lut=2 *) +module CFG2 ( + output Y, + input A, + input B +); + parameter [3:0] INIT = 4'h0; + assign Y = INIT >> {B, A}; + specify + (A => Y) = 238; + (B => Y) = 127; + endspecify +endmodule + +(* abc9_lut=3 *) +module CFG3 ( + output Y, + input A, + input B, + input C +); + parameter [7:0] INIT = 8'h0; + assign Y = INIT >> {C, B, A}; + specify + (A => Y) = 407; + (B => Y) = 238; + (C => Y) = 127; + endspecify +endmodule + +(* abc9_lut=3 *) +module CFG4 ( + output Y, + input A, + input B, + input C, + input D +); + parameter [15:0] INIT = 16'h0; + assign Y = INIT >> {D, C, B, A}; + specify + (A => Y) = 472; + (B => Y) = 407; + (C => Y) = 238; + (D => Y) = 127; + endspecify +endmodule + +module BUFF ( + input A, + output Y +); + assign Y = A; +endmodule + +module BUFD ( + input A, + output Y +); + assign Y = A; +endmodule + +module CLKINT ( + input A, + (* clkbuf_driver *) + output Y +); + assign Y = A; +endmodule + +module CLKINT_PRESERVE ( + input A, + (* clkbuf_driver *) + output Y +); + assign Y = A; +endmodule + +module GCLKINT ( + input A, EN, + (* clkbuf_driver *) + output Y +); + assign Y = A & EN; +endmodule + +module RCLKINT ( + input A, + (* clkbuf_driver *) + output Y +); + assign Y = A; +endmodule + +module RGCLKINT ( + input A, EN, + (* clkbuf_driver *) + output Y +); + assign Y = A & EN; +endmodule + +// sequential elements + +// MCHP_SYNC_SET_DFF and MCHP_SYNC_RESET_DFF are intermediate cell types to implement the simplification idiom for abc9 flow +// see: https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/abc_flow.html + +(* abc9_flop, lib_whitebox *) +module MCHP_SYNC_SET_DFF( + input D, + input CLK, + input Set, + input En, + output Q); + parameter [0:0] INIT = 1'b0; // unused + always @(posedge CLK) begin + if (En == 1) begin + if (Set == 0) + Q <= 1; + else + Q <= D; + end + end + + specify + $setup(D , posedge CLK &&& En && Set, 0); // neg setup not supported? + $setup(En, posedge CLK, 109); + $setup(Set, posedge CLK &&& En, 404); + if (En && !Set) (posedge CLK => (Q : 1'b1)) = 303; + if (En && Set) (posedge CLK => (Q : D)) = 303; + endspecify +endmodule + +(* abc9_flop, lib_whitebox *) +module MCHP_SYNC_RESET_DFF( + input D, + input CLK, + input Reset, + input En, + output Q); + parameter [0:0] INIT = 1'b0; // unused + always @(posedge C) begin + if (En == 1) begin + if (Reset == 0) + Q <= 0; + else + Q <= D; + end + end + + specify + $setup(D , posedge CLK &&& En && Reset, 0); // neg setup not supported? + $setup(En, posedge CLK, 109); + $setup(Reset, posedge CLK &&& En, 404); + if (En && !Reset) (posedge CLK => (Q : 1'b0)) = 303; + if (En && Reset) (posedge CLK => (Q : D)) = 303; + endspecify +endmodule + +module SLE ( + output Q, + input ADn, + input ALn, + (* clkbuf_sink *) + input CLK, + input D, + input LAT, + input SD, + input EN, + input SLn +); + reg q_latch, q_ff; + + always @(posedge CLK, negedge ALn) begin + if (!ALn) begin + q_ff <= !ADn; + end else if (EN) begin + if (!SLn) + q_ff <= SD; + else + q_ff <= D; + end + end + + always @* begin + if (!ALn) begin + q_latch <= !ADn; + end else if (CLK && EN) begin + if (!SLn) + q_ff <= SD; + else + q_ff <= D; + end + end + + assign Q = LAT ? q_latch : q_ff; +endmodule + +(* abc9_box, lib_whitebox *) +module ARI1 ( + (* abc9_carry *) + input FCI, + (* abc9_carry *) + output FCO, + + input A, B, C, D, + output Y, S +); + parameter [19:0] INIT = 20'h0; + wire [2:0] Fsel = {D, C, B}; + wire F0 = INIT[Fsel]; + wire F1 = INIT[8 + Fsel]; + wire Yout = A ? F1 : F0; + assign Y = Yout; + assign S = FCI ^ Yout; + wire G = INIT[16] ? (INIT[17] ? F1 : F0) : INIT[17]; + wire P = INIT[19] ? 1'b1 : (INIT[18] ? Yout : 1'b0); + assign FCO = P ? FCI : G; + + specify + //pin to pin path delay + (A => Y ) = 472; + (B => Y ) = 407; + (C => Y ) = 238; + (D => Y ) = 127; + (A => S ) = 572; + (B => S ) = 507; + (C => S ) = 338; + (D => S ) = 227; + (FCI => S ) = 100; + (A => FCO ) = 522; + (B => FCO ) = 457; + (C => FCO ) = 288; + (D => FCO ) = 177; + (FCI => FCO ) = 50; + endspecify +endmodule + +// module FCEND_BUFF +// module FCINIT_BUFF +// module FLASH_FREEZE +// module OSCILLATOR +// module SYSCTRL_RESET_STATUS +// module LIVE_PROBE_FB + +(* blackbox *) +module GCLKBUF ( + (* iopad_external_pin *) + input PAD, + input EN, + (* clkbuf_driver *) + output Y +); +endmodule + +(* blackbox *) +module GCLKBUF_DIFF ( + (* iopad_external_pin *) + input PADP, + (* iopad_external_pin *) + input PADN, + input EN, + (* clkbuf_driver *) + output Y +); +endmodule + +(* blackbox *) +module GCLKBIBUF ( + input D, + input E, + input EN, + (* iopad_external_pin *) + inout PAD, + (* clkbuf_driver *) + output Y +); +endmodule + +// module DFN1 +// module DFN1C0 +// module DFN1E1 +// module DFN1E1C0 +// module DFN1E1P0 +// module DFN1P0 +// module DLN1 +// module DLN1C0 +// module DLN1P0 + +module INV ( + input A, + output Y +); + assign Y = !A; +endmodule + +module INVD ( + input A, + output Y +); + assign Y = !A; +endmodule + +module MX2 ( + input A, B, S, + output Y +); + assign Y = S ? B : A; +endmodule + +module MX4 ( + input D0, D1, D2, D3, S0, S1, + output Y +); + assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0); +endmodule + +module NAND2 ( + input A, B, + output Y +); + assign Y = !(A & B); +endmodule + +module NAND3 ( + input A, B, C, + output Y +); + assign Y = !(A & B & C); +endmodule + +module NAND4 ( + input A, B, C, D, + output Y +); + assign Y = !(A & B & C & D); +endmodule + +module NOR2 ( + input A, B, + output Y +); + assign Y = !(A | B); +endmodule + +module NOR3 ( + input A, B, C, + output Y +); + assign Y = !(A | B | C); +endmodule + +module NOR4 ( + input A, B, C, D, + output Y +); + assign Y = !(A | B | C | D); +endmodule + +module OR2 ( + input A, B, + output Y +); + assign Y = A | B; +endmodule + +module OR3 ( + input A, B, C, + output Y +); + assign Y = A | B | C; +endmodule + +module OR4 ( + input A, B, C, D, + output Y +); + assign Y = A | B | C | D; +endmodule + +module XOR2 ( + input A, B, + output Y +); + assign Y = A ^ B; +endmodule + +module XOR3 ( + input A, B, C, + output Y +); + assign Y = A ^ B ^ C; +endmodule + +module XOR4 ( + input A, B, C, D, + output Y +); + assign Y = A ^ B ^ C ^ D; +endmodule + +module XOR8 ( + input A, B, C, D, E, F, G, H, + output Y +); + assign Y = A ^ B ^ C ^ D ^ E ^ F ^ G ^ H; +endmodule + +// module UJTAG + +module BIBUF ( + input D, + input E, + (* iopad_external_pin *) + inout PAD, + output Y +); + parameter IOSTD = ""; + assign PAD = E ? D : 1'bz; + assign Y = PAD; +endmodule + +(* blackbox *) +module BIBUF_DIFF ( + input D, + input E, + (* iopad_external_pin *) + inout PADP, + (* iopad_external_pin *) + inout PADN, + output Y +); + parameter IOSTD = ""; +endmodule + +module CLKBIBUF ( + input D, + input E, + (* iopad_external_pin *) + inout PAD, + (* clkbuf_driver *) + output Y +); + parameter IOSTD = ""; + assign PAD = E ? D : 1'bz; + assign Y = PAD; +endmodule + +module CLKBUF ( + (* iopad_external_pin *) + input PAD, + (* clkbuf_driver *) + output Y +); + parameter IOSTD = ""; + assign Y = PAD; + specify + (PAD => Y) = 50; + endspecify +endmodule + +(* blackbox *) +module CLKBUF_DIFF ( + (* iopad_external_pin *) + input PADP, + (* iopad_external_pin *) + input PADN, + (* clkbuf_driver *) + output Y +); + parameter IOSTD = ""; +endmodule + +module INBUF ( + (* iopad_external_pin *) + input PAD, + output Y +); + parameter IOSTD = ""; + assign Y = PAD; +endmodule + +(* blackbox *) +module INBUF_DIFF ( + (* iopad_external_pin *) + input PADP, + (* iopad_external_pin *) + input PADN, + output Y +); + parameter IOSTD = ""; +endmodule + +module OUTBUF ( + input D, + (* iopad_external_pin *) + output PAD +); + parameter IOSTD = ""; + assign PAD = D; +endmodule + +(* blackbox *) +module OUTBUF_DIFF ( + input D, + (* iopad_external_pin *) + output PADP, + (* iopad_external_pin *) + output PADN +); + parameter IOSTD = ""; +endmodule + +module TRIBUFF ( + input D, + input E, + (* iopad_external_pin *) + output PAD +); + parameter IOSTD = ""; + assign PAD = E ? D : 1'bz; +endmodule + +(* blackbox *) +module TRIBUFF_DIFF ( + input D, + input E, + (* iopad_external_pin *) + output PADP, + (* iopad_external_pin *) + output PADN +); + parameter IOSTD = ""; +endmodule + +// module DDR_IN +// module DDR_OUT +// module RAM1K18 +// module RAM64x18 +// module MACC + +(* blackbox *) +module SYSRESET ( + (* iopad_external_pin *) + input DEVRST_N, + output POWER_ON_RESET_N); +endmodule + + +(* blackbox *) +module XTLOSC ( + (* iopad_external_pin *) + input XTL, + output CLKOUT); + parameter [1:0] MODE = 2'h3; + parameter real FREQUENCY = 20.0; +endmodule + +(* blackbox *) +module RAM1K18 ( + input [13:0] A_ADDR, + input [2:0] A_BLK, + (* clkbuf_sink *) + input A_CLK, + input [17:0] A_DIN, + output [17:0] A_DOUT, + input [1:0] A_WEN, + input [2:0] A_WIDTH, + input A_WMODE, + input A_ARST_N, + input A_DOUT_LAT, + input A_DOUT_ARST_N, + (* clkbuf_sink *) + input A_DOUT_CLK, + input A_DOUT_EN, + input A_DOUT_SRST_N, + + input [13:0] B_ADDR, + input [2:0] B_BLK, + (* clkbuf_sink *) + input B_CLK, + input [17:0] B_DIN, + output [17:0] B_DOUT, + input [1:0] B_WEN, + input [2:0] B_WIDTH, + input B_WMODE, + input B_ARST_N, + input B_DOUT_LAT, + input B_DOUT_ARST_N, + (* clkbuf_sink *) + input B_DOUT_CLK, + input B_DOUT_EN, + input B_DOUT_SRST_N, + + input A_EN, + input B_EN, + input SII_LOCK, + output BUSY); +endmodule + +(* blackbox *) +module RAM64x18 ( + input [9:0] A_ADDR, + input [1:0] A_BLK, + input [2:0] A_WIDTH, + output [17:0] A_DOUT, + input A_DOUT_ARST_N, + (* clkbuf_sink *) + input A_DOUT_CLK, + input A_DOUT_EN, + input A_DOUT_LAT, + input A_DOUT_SRST_N, + (* clkbuf_sink *) + input A_ADDR_CLK, + input A_ADDR_EN, + input A_ADDR_LAT, + input A_ADDR_SRST_N, + input A_ADDR_ARST_N, + + input [9:0] B_ADDR, + input [1:0] B_BLK, + input [2:0] B_WIDTH, + output [17:0] B_DOUT, + input B_DOUT_ARST_N, + (* clkbuf_sink *) + input B_DOUT_CLK, + input B_DOUT_EN, + input B_DOUT_LAT, + input B_DOUT_SRST_N, + (* clkbuf_sink *) + input B_ADDR_CLK, + input B_ADDR_EN, + input B_ADDR_LAT, + input B_ADDR_SRST_N, + input B_ADDR_ARST_N, + + input [9:0] C_ADDR, + (* clkbuf_sink *) + input C_CLK, + input [17:0] C_DIN, + input C_WEN, + input [1:0] C_BLK, + input [2:0] C_WIDTH, + + input A_EN, + input B_EN, + input C_EN, + input SII_LOCK, + output BUSY); +endmodule + +(* blackbox *) +module MACC_PA ( + input DOTP, + input SIMD, + input OVFL_CARRYOUT_SEL, + input CLK, + input AL_N, + input [17:0] A, + input A_BYPASS, + input A_SRST_N, + input A_EN, + input [17:0] B, + input B_BYPASS, + input B_SRST_N, + input B_EN, + input [17:0] D, + input D_BYPASS, + input D_ARST_N, + input D_SRST_N, + input D_EN, + input CARRYIN, + input [47:0] C, + input C_BYPASS, + input C_ARST_N, + input C_SRST_N, + input C_EN, + input [47:0] CDIN, + output [47:0] P, + output OVFL_CARRYOUT, + input P_BYPASS, + input P_SRST_N, + input P_EN, + output [47:0] CDOUT, + input PASUB, + input PASUB_BYPASS, + input PASUB_AD_N, + input PASUB_SL_N, + input PASUB_SD_N, + input PASUB_EN, + input [1:0] CDIN_FDBK_SEL, + input CDIN_FDBK_SEL_BYPASS, + input [1:0] CDIN_FDBK_SEL_AD_N, + input CDIN_FDBK_SEL_SL_N, + input [1:0] CDIN_FDBK_SEL_SD_N, + input CDIN_FDBK_SEL_EN, + input ARSHFT17, + input ARSHFT17_BYPASS, + input ARSHFT17_AD_N, + input ARSHFT17_SL_N, + input ARSHFT17_SD_N, + input ARSHFT17_EN, + input SUB, + input SUB_BYPASS, + input SUB_AD_N, + input SUB_SL_N, + input SUB_SD_N, + input SUB_EN +); +endmodule + +(* blackbox *) +module RAM1K20 ( + input [13:0] A_ADDR, + input [2:0] A_BLK_EN, + input A_CLK, + input [19:0] A_DIN, + output [19:0] A_DOUT, + input [1:0] A_WEN, + input A_REN, + input [2:0] A_WIDTH, + input [1:0] A_WMODE, + input A_BYPASS, + input A_DOUT_EN, + input A_DOUT_SRST_N, + input A_DOUT_ARST_N, + input [13:0] B_ADDR, + input [2:0] B_BLK_EN, + input B_CLK, + input [19:0] B_DIN, + output [19:0] B_DOUT, + input [1:0] B_WEN, + input B_REN, + input [2:0] B_WIDTH, + input [1:0] B_WMODE, + input B_BYPASS, + input B_DOUT_EN, + input B_DOUT_SRST_N, + input B_DOUT_ARST_N, + input ECC_EN, + input ECC_BYPASS, + output SB_CORRECT, + output DB_DETECT, + input BUSY_FB, + output ACCESS_BUSY +); +parameter INIT0 = 1024'h0; +parameter INIT1 = 1024'h0; +parameter INIT2 = 1024'h0; +parameter INIT3 = 1024'h0; +parameter INIT4 = 1024'h0; +parameter INIT5 = 1024'h0; +parameter INIT6 = 1024'h0; +parameter INIT7 = 1024'h0; +parameter INIT8 = 1024'h0; +parameter INIT9 = 1024'h0; +parameter INIT10 = 1024'h0; +parameter INIT11 = 1024'h0; +parameter INIT12 = 1024'h0; +parameter INIT13 = 1024'h0; +parameter INIT14 = 1024'h0; +parameter INIT15 = 1024'h0; +parameter INIT16 = 1024'h0; +parameter INIT17 = 1024'h0; +parameter INIT18 = 1024'h0; +parameter INIT19 = 1024'h0; +endmodule + +(* blackbox *) +module RAM64x12 ( + input R_CLK, + input [5:0] R_ADDR, + input R_ADDR_BYPASS, + input R_ADDR_EN, + input R_ADDR_SL_N, + input R_ADDR_SD, + input R_ADDR_AL_N, + input R_ADDR_AD_N, + input BLK_EN, + output [11:0] R_DATA, + input R_DATA_BYPASS, + input R_DATA_EN, + input R_DATA_SL_N, + input R_DATA_SD, + input R_DATA_AL_N, + input R_DATA_AD_N, + + input W_CLK, + input [5:0] W_ADDR, + input [11:0] W_DATA, + input W_EN, + + input BUSY_FB, + output ACCESS_BUSY +); +endmodule \ No newline at end of file diff --git a/techlibs/mchp/mchp_dffopt.cc b/techlibs/mchp/mchp_dffopt.cc new file mode 100644 index 000000000..3e73ea6a3 --- /dev/null +++ b/techlibs/mchp/mchp_dffopt.cc @@ -0,0 +1,340 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +typedef std::pair> LutData; + +// Compute a LUT implementing (select ^ select_inv) ? alt_data : data. Returns true if successful. +bool merge_lut(LutData &result, const LutData &data, const LutData select, bool select_inv, SigBit alt_data, int max_lut_size) { + // First, gather input signals -- insert new signals at the beginning + // of the vector, so they don't disturb the likely-critical D LUT input + // timings. + result.second = data.second; + // D lut inputs initially start at 0. + int idx_data = 0; + // Now add the control input LUT inputs. + std::vector idx_sel; + for (auto bit : select.second) { + int idx = -1; + for (int i = 0; i < GetSize(result.second); i++) + if (result.second[i] == bit) + idx = i; + if (idx == -1) { + idx = 0; + // Insert new signal at the beginning and bump all indices. + result.second.insert(result.second.begin(), bit); + idx_data++; + for (int &sidx : idx_sel) + sidx++; + } + idx_sel.push_back(idx); + } + // Insert the Q signal, if any, to the slowest input -- it will have + // no problem meeting timing. + // This is to emulate CLK_EN, where output data is retained + int idx_alt = -1; + if (alt_data.wire) { + // Check if we already have it. + for (int i = 0; i < GetSize(result.second); i++) + if (result.second[i] == alt_data) + idx_alt = i; + // If not, add it. + if (idx_alt == -1) { + idx_alt = 0; + result.second.insert(result.second.begin(), alt_data); + idx_data++; + for (int &sidx : idx_sel) + sidx++; + } + } + + // If LUT would be too large, bail. + if (GetSize(result.second) > max_lut_size) + return false; + + // Okay, we're doing it — compute the LUT mask. + result.first = Const(0, 1 << GetSize(result.second)); + for (int i = 0; i < GetSize(result.first); i++) { + int sel_lut_idx = 0; + for (int j = 0; j < GetSize(select.second); j++) + if (i & 1 << idx_sel[j]) + sel_lut_idx |= 1 << j; + bool select_val = (select.first.bits[sel_lut_idx] == State::S1); + bool new_bit; + if (select_val ^ select_inv) { + // Use alt_data. + if (alt_data.wire) + new_bit = (i & 1 << idx_alt) != 0; + else + new_bit = alt_data.data == State::S1; + } else { + // Use original LUT. + int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); + new_bit = data.first.bits[lut_idx] == State::S1; + } + result.first.bits[i] = new_bit ? State::S1 : State::S0; + } + return true; +} + +struct MchpDffOptPass : public Pass { + MchpDffOptPass() : Pass("mchp_dffopt", "MCHP: optimize FF control signal usage") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" mchp_dffopt [options] [selection]\n"); + log("\n"); + log("Converts hardware clock enable and set/reset signals on FFs to emulation\n"); + log("using LUTs, if doing so would improve area. Operates on post-techmap LUT, DFF\n"); + log("cells. \n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing MCHP_DFFOPT pass (optimize FF control signal usage).\n"); + + size_t argidx; + int max_lut_size = 4; + + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + log("Optimizing FFs in %s.\n", log_id(module)); + + SigMap sigmap(module); + dict> bit_to_lut; + dict bit_uses; + + // Gather LUTs. + for (auto cell : module->selected_cells()) + { + for (auto port : cell->connections()) + for (auto bit : port.second) + bit_uses[sigmap(bit)]++; + if (cell->get_bool_attribute(ID::keep)) + continue; + if (cell->type == ID(INV)) { + SigBit sigout = sigmap(cell->getPort(ID::Y)); + SigBit sigin = sigmap(cell->getPort(ID::A)); + bit_to_lut[sigout] = make_pair(LutData(Const(1, 2), {sigin}), cell); // INIT = 01 + } else if (cell->type.in(ID(CFG1), ID(CFG2), ID(CFG3), ID(CFG4))) { + SigBit sigout = sigmap(cell->getPort(ID::Y)); + const Const &init = cell->getParam(ID::INIT); + std::vector sigin; + sigin.push_back(sigmap(cell->getPort(ID(A)))); + if (cell->type == ID(CFG1)) + goto lut_sigin_done; + sigin.push_back(sigmap(cell->getPort(ID(B)))); + if (cell->type == ID(CFG2)) + goto lut_sigin_done; + sigin.push_back(sigmap(cell->getPort(ID(C)))); + if (cell->type == ID(CFG3)) + goto lut_sigin_done; + sigin.push_back(sigmap(cell->getPort(ID(D)))); + +lut_sigin_done: + bit_to_lut[sigout] = make_pair(LutData(init, sigin), cell); + } + } + for (auto wire : module->wires()) + if (wire->port_output || wire->port_input) + for (int i = 0; i < GetSize(wire); i++) + bit_uses[sigmap(SigBit(wire, i))]++; + + // Iterate through FFs. + for (auto cell : module->selected_cells()) + { + + if (!cell->type.in(ID(SLE))) // not a SLE + continue; + if (cell->getPort(ID(LAT)).is_fully_ones()) // skip latch + continue; + if (cell->get_bool_attribute(ID::keep)) // keep attribute + continue; + if (!cell->getPort(ID(ALn)).is_fully_ones()) // async FF + continue; + + + const bool hasSyncLoad = cell->getPort(ID(SLn)).is_wire(); + const bool has_s = hasSyncLoad && cell->getPort(ID(SD)).is_fully_ones(); + const bool has_r = hasSyncLoad && cell->getPort(ID(SD)).is_fully_zero(); + + // SLE cannot have both synchronous set and reset implemented at the same time + log_assert(!(has_s && has_r)); + + // Don't bother if D has more than one use. + SigBit sig_D = sigmap(cell->getPort(ID::D)); + if (bit_uses[sig_D] > 2) + continue; + + // Find the D LUT. + auto it_D = bit_to_lut.find(sig_D); + if (it_D == bit_to_lut.end()) + continue; + LutData lut_d = it_D->second.first; + Cell *cell_d = it_D->second.second; + + + LutData lut_d_post_ce; + LutData lut_d_post_s; + LutData lut_d_post_r; + bool worthy_post_ce = false; + bool worthy_post_s = false; + bool worthy_post_r = false; + + // First, unmap CE. + SigBit sig_Q = sigmap(cell->getPort(ID::Q)); + SigBit sig_CE = sigmap(cell->getPort(ID(EN))); + LutData lut_ce = LutData(Const(2, 2), {sig_CE}); // INIT = 10 + auto it_CE = bit_to_lut.find(sig_CE); + if (it_CE != bit_to_lut.end()) + lut_ce = it_CE->second.first; + if (sig_CE.wire) { + // Merge CE LUT and D LUT into one. If it cannot be done, nothing to do about this FF. + if (!merge_lut(lut_d_post_ce, lut_d, lut_ce, true, sig_Q, max_lut_size)) + continue; + + // If this gets rid of a CE LUT, it's worth it. If not, it still may be worth it, if we can remove set/reset as well. + if (it_CE != bit_to_lut.end()) + worthy_post_ce = true; + } else if (sig_CE.data != State::S1) { + // Strange. Should not happen in a reasonable flow, so bail. + continue; + } else { + lut_d_post_ce = lut_d; + } + + // Second, unmap S, if any. + lut_d_post_s = lut_d_post_ce; + if (has_s) { + SigBit sig_S = sigmap(cell->getPort(ID(SLn))); + LutData lut_s = LutData(Const(2, 2), {sig_S}); // INIT = 10 + bool inv_s = true; // active low + auto it_S = bit_to_lut.find(sig_S); + if (it_S != bit_to_lut.end()) + lut_s = it_S->second.first; + if (sig_S.wire) { + // Merge S LUT and D LUT into one. If it cannot be done, try to at least merge CE. + if (!merge_lut(lut_d_post_s, lut_d_post_ce, lut_s, inv_s, SigBit(State::S1), max_lut_size)) + goto unmap; + // If this gets rid of an S LUT, it's worth it. + if (it_S != bit_to_lut.end()) + worthy_post_s = true; + } else if (sig_S.data != (inv_s ? State::S1 : State::S0)) { + // Strange. Should not happen in a reasonable flow, so bail. + continue; + } + } + + // Third, unmap R, if any. + lut_d_post_r = lut_d_post_s; + if (has_r) { + SigBit sig_R = sigmap(cell->getPort(ID(SLn))); + LutData lut_r = LutData(Const(2, 2), {sig_R}); // INIT = 10 + bool inv_r = true; // active low + auto it_R = bit_to_lut.find(sig_R); + if (it_R != bit_to_lut.end()) + lut_r = it_R->second.first; + if (sig_R.wire) { + // Merge R LUT and D LUT into one. If it cannot be done, try to at least merge CE/S. + if (!merge_lut(lut_d_post_r, lut_d_post_s, lut_r, inv_r, SigBit(State::S0), max_lut_size)) + goto unmap; + // If this gets rid of an S LUT, it's worth it. + if (it_R != bit_to_lut.end()) + worthy_post_r = true; + } else if (sig_R.data != (inv_r ? State::S1 : State::S0)) { + // Strange. Should not happen in a reasonable flow, so bail. + continue; + } + } + +unmap: + + // SLE cannot have both synchronous set and reset implemented at the same time + log_assert(!(worthy_post_r && worthy_post_s)); + + LutData final_lut; + if (worthy_post_r) { + final_lut = lut_d_post_r; + } else if (worthy_post_s) { + final_lut = lut_d_post_s; + } else if (worthy_post_ce) { + final_lut = lut_d_post_ce; + } else { + // Nothing to do here. + continue; + } + + std::string ports; + if (worthy_post_r) ports += " + R"; + if (worthy_post_s) ports += " + S"; + if (worthy_post_ce) ports += " + CE"; + log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports.c_str(), log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); + + // Okay, we're doing it. Unmap ports. + if ((has_s && worthy_post_s) || worthy_post_r) { + cell->setPort(ID(SLn), Const(1, 1)); + } + + // if we made it this far, clk enable is always merged into D + cell->setPort(ID(EN), Const(1, 1)); + + // Create the new LUT. + Cell *lut_cell = nullptr; + switch (GetSize(final_lut.second)) { + case 1: + lut_cell = module->addCell(NEW_ID, ID(CFG1)); + break; + case 2: + lut_cell = module->addCell(NEW_ID, ID(CFG2)); + break; + case 3: + lut_cell = module->addCell(NEW_ID, ID(CFG3)); + break; + case 4: + lut_cell = module->addCell(NEW_ID, ID(CFG4)); + break; + default: + log_assert(!"unknown lut size"); + } + lut_cell->attributes = cell_d->attributes; + Wire *lut_out = module->addWire(NEW_ID); + lut_cell->setParam(ID::INIT, final_lut.first); + cell->setPort(ID::D, lut_out); + lut_cell->setPort(ID::Y, lut_out); + lut_cell->setPort(ID(A), final_lut.second[0]); + if (GetSize(final_lut.second) >= 2) + lut_cell->setPort(ID(B), final_lut.second[1]); + if (GetSize(final_lut.second) >= 3) + lut_cell->setPort(ID(C), final_lut.second[2]); + if (GetSize(final_lut.second) >= 4) + lut_cell->setPort(ID(D), final_lut.second[3]); + } + } + } +} MchpDffOptPass; + +PRIVATE_NAMESPACE_END + diff --git a/techlibs/mchp/pf_dsp_map.v b/techlibs/mchp/pf_dsp_map.v new file mode 100644 index 000000000..a6b65a421 --- /dev/null +++ b/techlibs/mchp/pf_dsp_map.v @@ -0,0 +1,95 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + + wire [47:0] P_48; + // For pin descriptions, see Section 9 of PolarFire FPGA Macro Library Guide: + // https://coredocs.s3.amazonaws.com/Libero/2021_2/Tool/pf_mlg.pdf + MACC_PA _TECHMAP_REPLACE_ ( + .DOTP(1'b0), + .SIMD(1'b0), + .OVFL_CARRYOUT_SEL(1'b0), + + .AL_N(1'b1), + .A(A), + .A_BYPASS(1'b1), + .A_SRST_N(1'b1), + .A_EN(1'b1), + + .B(B), + .B_BYPASS(1'b1), + .B_SRST_N(1'b1), + .B_EN(1'b1), + + .D(18'b0), + .D_BYPASS(1'b1), + .D_ARST_N(1'b1), + .D_SRST_N(1'b1), + .D_EN(1'b1), + + .CARRYIN(1'b0), + .C(48'b0), + .C_BYPASS(1'b1), + .C_ARST_N(1'b1), + .C_SRST_N(1'b1), + .C_EN(1'b1), + + + .P(P_48), + + .P_BYPASS(1'b1), + .P_SRST_N(1'b1), + .P_EN(1'b1), + + .PASUB(1'b0), + .PASUB_BYPASS(1'b1), + .PASUB_AD_N(1'b0), + .PASUB_SL_N(1'b1), + .PASUB_SD_N(1'b0), + .PASUB_EN(1'b1), + + .CDIN_FDBK_SEL(2'b00), + .CDIN_FDBK_SEL_BYPASS(1'b1), + .CDIN_FDBK_SEL_AD_N(2'b00), + .CDIN_FDBK_SEL_SL_N(1'b1), + .CDIN_FDBK_SEL_SD_N(2'b00), + .CDIN_FDBK_SEL_EN(1'b1), + + .ARSHFT17(1'b0), + .ARSHFT17_BYPASS(1'b1), + .ARSHFT17_AD_N(1'b0), + .ARSHFT17_SL_N(1'b1), + .ARSHFT17_SD_N(1'b0), + .ARSHFT17_EN(1'b1), + + .SUB(1'b0), + .SUB_BYPASS(1'b1), + .SUB_AD_N(1'b0), + .SUB_SL_N(1'b1), + .SUB_SD_N(1'b0), + .SUB_EN(1'b1) + + ); + assign Y = P_48; +endmodule diff --git a/techlibs/mchp/synth_mchp.cc b/techlibs/mchp/synth_mchp.cc new file mode 100644 index 000000000..e5fe7d484 --- /dev/null +++ b/techlibs/mchp/synth_mchp.cc @@ -0,0 +1,543 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "kernel/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SynthMchpPass : public ScriptPass +{ + SynthMchpPass() : ScriptPass("synth_mchp", "synthesis for Microchip FPGAs") { } + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" synth_mchp [options]\n"); + log("\n"); + log("This command runs synthesis for Microchip FPGAs. Operating on\n"); + log("partly selected designs is not supported (you must submit a fully-selected \n"); + log("design). This command creates netlists that are compatible with Microchip \n"); + log("PolarFire devices.\n"); + log("\n"); + log(" -top \n"); + log(" use the specified module as the top module\n"); + log("\n"); + log(" -family \n"); + log(" Run synthesis for the specified Microchip architecture. \n"); + log(" Generate the synthesis netlist for the specified family.\n"); + log(" supported values:\n"); + log(" - pf: PolarFire\n"); + log("\n"); + log(" -edif \n"); + log(" Write the design to the specified edif file. Writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -blif \n"); + log(" Write the design to the specified BLIF file. Writing of an output file\n"); + log(" is omitted if this parameter is not specified.\n"); + log("\n"); + log(" -nobram\n"); + log(" Do not use block RAM cells in output netlist\n"); + log("\n"); + log(" -nocarry\n"); + log(" Do not use ARI1 cells in output netlist\n"); + log("\n"); + log(" -nodsp\n"); + log(" Do not use MATH blocks to implement multipliers and associated logic\n"); + log("\n"); + log(" -noiopad\n"); + log(" Disable I/O buffer insertion (useful for hierarchical or \n"); + log(" out-of-context flows)\n"); + log("\n"); + log(" -noclkbuf\n"); + log(" Disable automatic clock buffer insertion\n"); + log("\n"); + log(" -run :\n"); + log(" Only run the commands between the labels (see below). an empty\n"); + log(" 'from_label' is synonymous to 'begin', and empty 'to_label' is\n"); + log(" synonymous to the end of the command list.\n"); + log("\n"); + log(" -flatten\n"); + log(" Flatten design before synthesis.\n"); + log("\n"); + log(" -flatten_before_abc\n"); + log(" Flatten design before abc tech mapping.\n"); + log("\n"); + log(" -dff\n"); + log(" Run 'abc'/'abc9' with -dff option\n"); + log("\n"); + log(" -retime\n"); + log(" Run 'abc' with '-D 1' option to enable flip-flop retiming.\n"); + log(" implies -dff.\n"); + log("\n"); + log(" -abc9\n"); + log(" Use new ABC9 flow (EXPERIMENTAL)\n"); + log("\n"); + log("\n"); + log("The following commands are executed by this synthesis command:\n"); + help_script(); + log("\n"); + } + + std::string top_opt, edif_file, blif_file, family; + bool flatten, retime, noiopad, noclkbuf, nobram, nocarry, nowidelut, nodsp; + bool abc9, dff; + bool flatten_before_abc; + int lut_size; + + // debug dump switches + bool debug_memory, debug_carry; + + void clear_flags() override + { + top_opt = "-auto-top"; + edif_file.clear(); + blif_file.clear(); + family = "pf"; + flatten = false; + retime = false; + noiopad = false; + noclkbuf = false; + nocarry = false; + nobram = false; + nowidelut = false; + nodsp = false; + abc9 = false; + dff = false; + flatten_before_abc = false; + lut_size = 4; + + debug_memory = false; + debug_carry = false; + } + + void execute(std::vector args, RTLIL::Design *design) override + { + std::string run_from, run_to; + clear_flags(); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-top" && argidx+1 < args.size()) { + top_opt = "-top " + args[++argidx]; + continue; + } + if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) { + family = args[++argidx]; + continue; + } + if (args[argidx] == "-edif" && argidx+1 < args.size()) { + edif_file = args[++argidx]; + continue; + } + if (args[argidx] == "-blif" && argidx+1 < args.size()) { + blif_file = args[++argidx]; + continue; + } + if (args[argidx] == "-run" && argidx+1 < args.size()) { + size_t pos = args[argidx+1].find(':'); + if (pos == std::string::npos) + break; + run_from = args[++argidx].substr(0, pos); + run_to = args[argidx].substr(pos+1); + continue; + } + if (args[argidx] == "-flatten") { + flatten = true; + continue; + } + if (args[argidx] == "-flatten_before_abc") { + flatten_before_abc = true; + continue; + } + if (args[argidx] == "-retime") { + dff = true; + retime = true; + continue; + } + if (args[argidx] == "-nocarry") { + nocarry = true; + continue; + } + if (args[argidx] == "-nowidelut") { + nowidelut = true; + continue; + } + if (args[argidx] == "-iopad") { + continue; + } + if (args[argidx] == "-noiopad") { + noiopad = true; + continue; + } + if (args[argidx] == "-noclkbuf") { + noclkbuf = true; + continue; + } + if (args[argidx] == "-nocarry") { + nocarry = true; + continue; + } + if (args[argidx] == "-nobram") { + nobram = true; + continue; + } + if (args[argidx] == "-abc9") { + abc9 = true; + continue; + } + if (args[argidx] == "-nodsp") { + nodsp = true; + continue; + } + if (args[argidx] == "-dff") { + dff = true; + continue; + } + if (args[argidx] == "-debug_memory") { + debug_memory = true; + continue; + } + if (args[argidx] == "-debug_carry") { + debug_carry = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (family == "pf") { + lut_size = 4; + } else { + log_cmd_error("Invalid Microchip -family setting: '%s'.\n", family.c_str()); + } + + if (!design->full_selection()) + log_cmd_error("This command only operates on fully selected designs!\n"); + + if (abc9 && retime) + log_cmd_error("-retime option not currently compatible with -abc9!\n"); + + + log_header(design, "Executing SYNTH_MCHP pass.\n"); + log_push(); + + run_script(design, run_from, run_to); + + log_pop(); + } + + void script() override + { + std::string lut_size_s = std::to_string(lut_size); + if (help_mode) + lut_size_s = "[4]"; + + if (check_label("begin")) { + std::string read_args; + read_args += " -lib -specify +/mchp/cells_sim.v"; + run("read_verilog" + read_args); + + run(stringf("hierarchy -check %s", top_opt.c_str())); + } + + if (check_label("prepare")) { + run("proc"); + if (flatten || help_mode) + run("flatten", "(with '-flatten')"); + if (active_design) + active_design->scratchpad_unset("tribuf.added_something"); + run("tribuf -logic"); + if (noiopad && active_design && active_design->scratchpad_get_bool("tribuf.added_something")) + log_error("Tristate buffers are unsupported without the '-iopad' option.\n"); + run("deminout"); + run("opt_expr"); + run("opt_clean"); + run("check"); + run("opt -nodffe -nosdff"); + run("fsm"); + run("opt"); + + run("wreduce"); + run("peepopt"); + run("opt_clean"); + } + + if (check_label("map_dsp", "(skip if '-nodsp')")) { + if (!nodsp || help_mode) { + run("memory_dff"); // mchp_dsp will merge registers, reserve memory port registers first + if (help_mode) + run("techmap -map +/mul2dsp.v -map +/mchp/{family}_dsp_map.v {options}"); + else if (family == "pf") // Microchip - map multipliers to DSP + run("techmap -map +/mul2dsp.v -map +/mchp/pf_dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 " + "-D DSP_A_MAXWIDTH_PARTIAL=18 " // Partial multipliers are intentionally + // limited to 18x18 in order to take + // advantage of the (PCOUT >> 17) -> PCIN + // dedicated cascade chain capability + "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 " // Blocks Nx1 multipliers + "-D DSP_Y_MINWIDTH=9 " + "-D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL18X18"); + + run("select a:mul2dsp"); + run("setattr -unset mul2dsp"); + run("opt_expr -fine"); + run("wreduce"); + run("select -clear"); + if (help_mode) + run("mchp_dsp -family "); + else if (family == "pf") // Microchip - absorb cells into DSP + run("mchp_dsp -family " + family); + + run("chtype -set $mul t:$__soft_mul"); + } + } + + if (check_label("coarse")) { + run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=" + lut_size_s); + run("alumacc"); + run("share"); + run("opt"); + run("memory -nomap"); + run("opt_clean"); + } + + if (check_label("map_memory")) { + std::string params = ""; + std::string LSRAM_map = "+/mchp/LSRAM_map.v"; + std::string uSRAM_map = "+/mchp/uSRAM_map.v"; + if (debug_memory) run("write_verilog -noexpr memory_map_pre.vm"); + if (help_mode) { + params = " [...]"; + } else { + + if (family == "pf") { + // cost of a single bit for memory lowered to soft logic + params += " -logic-cost-rom 0.015625"; + + params += " -lib +/mchp/LSRAM.txt"; + params += " -lib +/mchp/uSRAM.txt"; + LSRAM_map = "+/mchp/LSRAM_map.v"; + uSRAM_map = "+/mchp/uSRAM_map.v"; + } + if (nobram) params += " -no-auto-block"; + } + + // transform memories into intermediate cells + // Cost based transformation. The cost is assigned by us for each cell. + run("memory_libmap" + params); + if (debug_memory) run("write_verilog -noexpr memory_map_libmap.vm"); + + // map intermediate cells to actual RAM macros + // NOTE: order doesnt matter here + run("techmap -map " + LSRAM_map); + run("techmap -map " + uSRAM_map); + if (debug_memory) run("write_verilog -noexpr memory_map_final.vm"); + } + + if (check_label("map_ffram")) { + run("opt -fast -full"); + + + // blast unmapped RAM to flops or LUTs + run("memory_map"); + } + + if (check_label("fine")) { + run("opt -full"); + + if (debug_carry) run("write_verilog -noexpr ARI1_cells.vm"); + + if (!nocarry) { + // converts $mux -> $_MUX_ to allow muxcover to work + run("simplemap t:$mux"); + + // converts $and/$or/$xor to gate representation for extract_reduce to work + run("simplemap t:$xor"); // only mapping reduce_xor + + // mapping based on Yosys internal gates + if (debug_carry) run("write_verilog -noexpr ARI1_pre.vm"); + + // collapse $_AND_/$_OR_/$_XOR_ chains into reduction cells + run("extract_reduce"); + + if (debug_carry) run("write_verilog -noexpr ARI1_extract_reduce.vm"); + + // pack mux trees into $_MUX4_ + run("muxcover -nodecode -mux4=220"); + + if (debug_carry) run("write_verilog -noexpr ARI1_muxcover.vm"); + + run("techmap -map +/mchp/arith_map.v"); + if (debug_carry) run("write_verilog -noexpr ARI1_post.vm"); + + } + + // convert all remaining cells to gates + run("techmap -map +/techmap.v"); + + run("opt -fast"); + } + + if (check_label("map_cells")) { + // Needs to be done before logic optimization, so that inverters (inserted + // here because of negative-polarity output enable) are handled. + if (help_mode || !noiopad) { + run("iopadmap -bits -inpad INBUF Y:PAD -outpad OUTBUF D:PAD -toutpad TRIBUFF E:D:PAD -tinoutpad BIBUF E:Y:D:PAD", "(unless -noiobs)"); + } + + std::string techmap_args = "-map +/techmap.v -map +/mchp/cells_map.v"; + run("techmap " + techmap_args); + run("clean"); + } + + if (check_label("map_ffs")) { + // dfflegalize : Converts FFs to types supported by the target + // this can convert less capable cells into more capable cells (e.g. dff -> dffe) + + // Based on PolarFire® FPGA Macro Library Guide + // D-flop: + // active high enable + // active low clear or active low set + // Latch: + // active low clear or active low set + // SLE (can implement D-flop/Latch): + // active high EN + // active low async load (set/reset) with static load configuration via ADn (Q = ~ADn) + // active low sync load (set/reset) with static load configuration via SD + // static latch configuration bit + // init not supported + + // Yosys internal cell description + // see: https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/formats/cell_library.html + // see: common/simcells.v + // $_DFF_[NP]_ (regular dff) + // $_DFFE_[NP][NP]_ (enable) + // $_DFF_[NP][NP][01]_ (async reset to 0/1) + // $_DFFE_[NP][NP][01][NP]_ (async reset to 0/1 + enable) + // $_ALDFF_[NP][NP]_ (async load) + // $_ALDFFE_[NP][NP][NP]_ (async load + enable) + // $_DFFSR_[NP][NP][NP]_ (async set & reset) + // $_DFFSRE_[NP][NP][NP][NP]_ (async set & reset + enable) + // $_SDFF_[NP][NP][01]_ (sync reset to 0/1) + // $_SDFFE_[NP][NP][01][NP]_ (sync reset to 0/1 + enable, reset prioritize over enable) + // $_SDFFCE_[NP][NP][01][NP]_ (sync reset to 0/1 + enable, enable prioritize over reset) + // $_SR_[NP][NP]_ (set/reset latch) + // $_DLATCH_[NP]_ (D-latch) + // $_DLATCH_[NP][NP][01]_ (D-latch + reset to 0/1) + // $_DLATCHSR_[NP][NP][NP]_ (D-latch + set + reset) + + + if (family == "pf") { + std::string params = ""; + + + // D-flop with async reset and enable + // posedge CLK, active low reset to 1 or 0, active high EN + params += " -cell $_DFFE_PN?P_ 01"; + + // D-flop with sync reset and enable, enable takes priority over reset + // posedge CLK, active low reset to 1 or 0, active high EN + params += " -cell $_SDFFCE_PN?P_ 01"; + + // D-latch + reset to 0/1 + // posedge CLK, active low reset to 1 or 0 + params += " -cell $_DLATCH_PN?_ 01"; + + run("dfflegalize" + params, "(Converts FFs to supported types)"); + } + + + if (abc9 || help_mode) { + if (dff || help_mode) + run("zinit -all w:* t:$_SDFFCE_*", "('-dff' only)"); + run("techmap -D NO_LUT -map +/mchp/cells_map.v", "('-abc9' only)"); + } + } + + if (check_label("map_luts")) { + run("opt_expr -mux_undef -noclkinv"); + if (flatten_before_abc) + run("flatten"); + if (help_mode) + run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); + else if (abc9) { + + std::string abc9_opts; + // for the if command in abc to specify wire delay between adjects LUTs (default = 0) + // NOTE: should not have 0 wire delay between LUTs, + // otherwise abc might use LUT2+LUT3 instead of single LUT4 + abc9_opts += " -W 300"; + if (nowidelut) + abc9_opts += stringf(" -maxlut %d", lut_size); + if (dff) + abc9_opts += " -dff"; + run("abc9" + abc9_opts); + } + else { + std::string abc_opts = " -lut " + lut_size_s; + if (dff) + abc_opts += " -dff"; + if (retime) + abc_opts += " -D 1"; + run("abc" + abc_opts); + } + run("clean"); + + if (help_mode || !abc9) + run("techmap -D NO_LUT -map +/mchp/cells_map.v", "(only if not '-abc9')"); + std::string techmap_args = "-map +/mchp/cells_map.v -D FINAL_MAP"; + techmap_args += " -D LUT_WIDTH=" + lut_size_s; + run("techmap " + techmap_args); + + if (help_mode || lut_size == 4) + run("mchp_dffopt"); + + + } + + run("clkbufmap -buf CLKINT Y:A -inpad CLKBUF Y:PAD"); + + run("clean -purge"); + + + if (check_label("check")) { + run("hierarchy -check"); + run("stat"); + run("check -noinit"); + run("blackbox =A:whitebox"); + } + + if (check_label("edif")) { + if (!edif_file.empty() || help_mode) + run(stringf("write_edif -pvector bra %s", edif_file.c_str())); + } + + if (check_label("blif")) { + if (!blif_file.empty() || help_mode) + run(stringf("write_blif %s", blif_file.c_str())); + } + } +} SynthMchpPass; + +PRIVATE_NAMESPACE_END diff --git a/techlibs/mchp/tests/Registers/Registers.v b/techlibs/mchp/tests/Registers/Registers.v new file mode 100644 index 000000000..b5bd6f4af --- /dev/null +++ b/techlibs/mchp/tests/Registers/Registers.v @@ -0,0 +1,38 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module Registers( + input clk, + input en, + input rst, + input D, + output Q +); +parameter LOAD_DATA = 1; + +// active low async reset +always @(posedge clk, negedge rst) begin + if (rst == 0) begin + Q <= LOAD_DATA; + end else if(en) begin + Q <= D; + end +end + + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/Registers/Registers.ys b/techlibs/mchp/tests/Registers/Registers.ys new file mode 100644 index 000000000..c83376fdd --- /dev/null +++ b/techlibs/mchp/tests/Registers/Registers.ys @@ -0,0 +1,23 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# read verilog files +read_verilog Registers.v + +synth_mchp -top Registers -abc9 -family pf -noiopad + +# write final outputfile +write_verilog -noexpr Registers.vm diff --git a/techlibs/mchp/tests/carryout/carryout.v b/techlibs/mchp/tests/carryout/carryout.v new file mode 100644 index 000000000..c109435b8 --- /dev/null +++ b/techlibs/mchp/tests/carryout/carryout.v @@ -0,0 +1,34 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module carryout (cout,out,a, b,c); +parameter n = 6; +parameter k = 2; +output reg [k*(n+1)-1:0] out; +output reg cout; +input [n:0] a; +input [n:0] b; +input [n-1:0] c; + + always @(a,b,c) + begin + {cout,out} = a * b + c; + + end + +endmodule diff --git a/techlibs/mchp/tests/carryout/carryout.ys b/techlibs/mchp/tests/carryout/carryout.ys new file mode 100644 index 000000000..1697bc893 --- /dev/null +++ b/techlibs/mchp/tests/carryout/carryout.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog carryout.v + +synth_mchp -top carryout -abc9 -family pf -noiopad + +write_verilog -noexpr carryout.vm diff --git a/techlibs/mchp/tests/cascade/cascade.v b/techlibs/mchp/tests/cascade/cascade.v new file mode 100644 index 000000000..6be738846 --- /dev/null +++ b/techlibs/mchp/tests/cascade/cascade.v @@ -0,0 +1,38 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module cascade( + input signed [5:0] in_A, + input signed [4:0] in_B, + input signed [4:0] in_D, + output signed [11:0] out_P, + + input signed [4:0] casA, + input signed [4:0] casB + +); + +wire signed [9:0] cascade; +// first dsp +assign cascade = casA * casB; + +// second dsp +assign out_P = in_A * (in_B + in_D) + cascade; + + +endmodule diff --git a/techlibs/mchp/tests/cascade/cascade.ys b/techlibs/mchp/tests/cascade/cascade.ys new file mode 100644 index 000000000..f7017913d --- /dev/null +++ b/techlibs/mchp/tests/cascade/cascade.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog cascade.v + +synth_mchp -top cascade -abc9 -family pf -noiopad + +write_verilog -noexpr cascade.vm diff --git a/techlibs/mchp/tests/dff_opt/dff_opt.v b/techlibs/mchp/tests/dff_opt/dff_opt.v new file mode 100644 index 000000000..b14bf4be5 --- /dev/null +++ b/techlibs/mchp/tests/dff_opt/dff_opt.v @@ -0,0 +1,42 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module dff_opt( + input clk, + input [1:0] D_comb, + input [1:0] EN_comb, + input [1:0] RST_comb, + output bar +); + +// DFF with enable that can be merged into D + +reg foo; + +assign bar = foo; + +// sync reset +always@(posedge clk) begin + if (&RST_comb) begin + foo <= 0; + end else begin + foo <= &D_comb; + end +end + +endmodule diff --git a/techlibs/mchp/tests/dff_opt/dff_opt.ys b/techlibs/mchp/tests/dff_opt/dff_opt.ys new file mode 100644 index 000000000..746444c34 --- /dev/null +++ b/techlibs/mchp/tests/dff_opt/dff_opt.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +read_verilog dff_opt.v + +synth_mchp -top dff_opt -abc9 -family pf -noiopad + +# write final outputfile +write_verilog -noexpr dff_opt.vm diff --git a/techlibs/mchp/tests/full_dsp/full_dsp.v b/techlibs/mchp/tests/full_dsp/full_dsp.v new file mode 100644 index 000000000..a99a4ee1c --- /dev/null +++ b/techlibs/mchp/tests/full_dsp/full_dsp.v @@ -0,0 +1,30 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +module full_dsp( + input signed[5:0] in_A, + input signed [4:0] in_B, + input signed [11:0] in_C, + input signed [4:0] in_D, + + output signed [12:0] out_Y +); + +assign out_Y = ((in_D + in_B)*in_A)+in_C; + + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/full_dsp/full_dsp.ys b/techlibs/mchp/tests/full_dsp/full_dsp.ys new file mode 100644 index 000000000..01bb95f54 --- /dev/null +++ b/techlibs/mchp/tests/full_dsp/full_dsp.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog full_dsp.v + +synth_mchp -top full_dsp -abc9 -family pf -noiopad + +write_verilog -noexpr full_dsp.vm diff --git a/techlibs/mchp/tests/large_mult/large_mult.v b/techlibs/mchp/tests/large_mult/large_mult.v new file mode 100644 index 000000000..9f7ad6f92 --- /dev/null +++ b/techlibs/mchp/tests/large_mult/large_mult.v @@ -0,0 +1,25 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module large_mult( + input signed [20:0] in1, + input signed [17:0] in2, + output signed [38:0] out1 +); +assign out1 = in1 * in2; +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/large_mult/large_mult.ys b/techlibs/mchp/tests/large_mult/large_mult.ys new file mode 100644 index 000000000..3779a26d6 --- /dev/null +++ b/techlibs/mchp/tests/large_mult/large_mult.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog large_mult.v + +synth_mchp -top large_mult -abc9 -family pf -noiopad + +write_verilog -noexpr large_mult.vm diff --git a/techlibs/mchp/tests/mac/mac.v b/techlibs/mchp/tests/mac/mac.v new file mode 100644 index 000000000..e32b21867 --- /dev/null +++ b/techlibs/mchp/tests/mac/mac.v @@ -0,0 +1,43 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module mac( + input clk, + input signed [4:0] in_A, + input signed [4:0] in_B, + input signed [4:0] in_D, + output reg signed [11:0] out_P, + + input srst_P, + + input signed [4:0] casA, + input signed [4:0] casB + +); + + +// sync reset P +always@(posedge clk) begin + if (~srst_P) begin + out_P <= 12'h000; + end else begin + out_P <= in_A * (in_B + in_D) + out_P; + end +end + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/mac/mac.ys b/techlibs/mchp/tests/mac/mac.ys new file mode 100644 index 000000000..595044368 --- /dev/null +++ b/techlibs/mchp/tests/mac/mac.ys @@ -0,0 +1,24 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# read verilog files +read_verilog mac.v + +# run the synth flow, specifies top module and additional parameters +synth_mchp -top mac -abc9 -family pf -noiopad + +# write final outputfile +write_verilog -noexpr mac.vm diff --git a/techlibs/mchp/tests/postAdd_mult/postAdd_mult.v b/techlibs/mchp/tests/postAdd_mult/postAdd_mult.v new file mode 100644 index 000000000..90a758dbc --- /dev/null +++ b/techlibs/mchp/tests/postAdd_mult/postAdd_mult.v @@ -0,0 +1,30 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module postAdd_mult( + input signed[17:0] in_A, + input signed [17:0] in_B, + input signed [17:0] in_C, + + output signed [35:0] out_Y +); + +assign out_Y = (in_B*in_A)+in_C; + + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/postAdd_mult/postAdd_mult.ys b/techlibs/mchp/tests/postAdd_mult/postAdd_mult.ys new file mode 100644 index 000000000..3a3586c88 --- /dev/null +++ b/techlibs/mchp/tests/postAdd_mult/postAdd_mult.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog postAdd_mult.v + +synth_mchp -top postAdd_mult -abc9 -family pf -noiopad + +write_verilog -noexpr postAdd_mult.vm diff --git a/techlibs/mchp/tests/post_adder/post_adder.v b/techlibs/mchp/tests/post_adder/post_adder.v new file mode 100644 index 000000000..13d954141 --- /dev/null +++ b/techlibs/mchp/tests/post_adder/post_adder.v @@ -0,0 +1,32 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module post_adder( + input signed [5:0] in_A, + input signed [4:0] in_B, + input signed [4:0] in_D, + input signed [11:0] in_C, + + output [12:0] out_Y +); + +assign out_Y = (in_D + in_B) * in_A + in_C; + + + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/post_adder/post_adder.ys b/techlibs/mchp/tests/post_adder/post_adder.ys new file mode 100644 index 000000000..0fa613f67 --- /dev/null +++ b/techlibs/mchp/tests/post_adder/post_adder.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog post_adder.v + +synth_mchp -top post_adder -abc9 -family pf + +write_verilog -noexpr post_adder.vm diff --git a/techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.v b/techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.v new file mode 100644 index 000000000..2343dd1a4 --- /dev/null +++ b/techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.v @@ -0,0 +1,30 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module pre_adder_dsp( + input signed [5:0] in_A, + input signed [4:0] in_B, + input signed [4:0] in_D, + + output [11:0] out_Y +); + +assign out_Y = in_A * (in_B + in_D); + + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.ys b/techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.ys new file mode 100644 index 000000000..82bc56bd1 --- /dev/null +++ b/techlibs/mchp/tests/pre_adder_dsp/pre_adder_dsp.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog pre_adder_dsp.v + +synth_mchp -top pre_adder_dsp -abc9 -family pf -noiopad + +write_verilog -noexpr pre_adder_dsp.vm diff --git a/techlibs/mchp/tests/ram_SDP/ram_SDP.v b/techlibs/mchp/tests/ram_SDP/ram_SDP.v new file mode 100644 index 000000000..30c724256 --- /dev/null +++ b/techlibs/mchp/tests/ram_SDP/ram_SDP.v @@ -0,0 +1,39 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module ram_SDP(data,waddr,we,clk,q); +parameter d_width = 32; +parameter addr_width = 8; +parameter mem_depth = 256; +input [d_width-1:0] data; +input [addr_width-1:0] waddr; +input we, clk; +output reg [d_width-1:0] q; + +reg [d_width-1:0] mem [mem_depth-1:0]; + +always @(posedge clk) begin + if (we) begin + mem[waddr] <= data; + end else begin + q <= mem[waddr]; + end +end + +endmodule + diff --git a/techlibs/mchp/tests/ram_SDP/ram_SDP.ys b/techlibs/mchp/tests/ram_SDP/ram_SDP.ys new file mode 100644 index 000000000..4ab129990 --- /dev/null +++ b/techlibs/mchp/tests/ram_SDP/ram_SDP.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog ram_SDP.v + +synth_mchp -top ram_SDP -abc9 -family pf -noiopad + +write_verilog -noexpr ram_SDP.vm diff --git a/techlibs/mchp/tests/ram_TDP/ram_TDP.v b/techlibs/mchp/tests/ram_TDP/ram_TDP.v new file mode 100644 index 000000000..d22357450 --- /dev/null +++ b/techlibs/mchp/tests/ram_TDP/ram_TDP.v @@ -0,0 +1,56 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module ram_TDP (clka,clkb,wea,addra,dataina,qa,web,addrb,datainb,qb); +parameter addr_width = 10; +parameter data_width = 2; +input clka,clkb,wea,web; +input [data_width - 1 : 0] dataina,datainb; +input [addr_width - 1 : 0] addra,addrb; +output reg [data_width - 1 : 0] qa,qb; +reg [addr_width - 1 : 0] addra_reg, addrb_reg; +reg [data_width - 1 : 0] mem [(2**addr_width) - 1 : 0]; + +always @ (posedge clka) + begin + addra_reg <= addra; + if(wea) + mem[addra] <= dataina; + end + +always @ (posedge clkb) +begin +addrb_reg <= addrb; +if(web) +mem[addrb] <= datainb; +end + +always @ (posedge clka) +begin +if(~wea) +qa <= mem[addra]; +else qa <= dataina; +end + +always @ (posedge clkb) +begin +if(~web) +qb <= mem[addrb]; +else qb <= datainb; +end +endmodule diff --git a/techlibs/mchp/tests/ram_TDP/ram_TDP.ys b/techlibs/mchp/tests/ram_TDP/ram_TDP.ys new file mode 100644 index 000000000..ea98facd5 --- /dev/null +++ b/techlibs/mchp/tests/ram_TDP/ram_TDP.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog ram_TDP.v + +synth_mchp -top ram_TDP -abc9 -family pf -noiopad -debug_memory + +write_verilog -noexpr ram_TDP.vm diff --git a/techlibs/mchp/tests/reduce/reduce.v b/techlibs/mchp/tests/reduce/reduce.v new file mode 100644 index 000000000..603d03173 --- /dev/null +++ b/techlibs/mchp/tests/reduce/reduce.v @@ -0,0 +1,29 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module reduce( + input [7:0] data, + output Y + + ); + + +assign Y = ^data; + +endmodule + diff --git a/techlibs/mchp/tests/reduce/reduce.ys b/techlibs/mchp/tests/reduce/reduce.ys new file mode 100644 index 000000000..693f1cdeb --- /dev/null +++ b/techlibs/mchp/tests/reduce/reduce.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog reduce.v + +synth_mchp -top reduce -abc9 -family pf -noiopad + +write_verilog -noexpr reduce.vm diff --git a/techlibs/mchp/tests/reg_c/reg_c.v b/techlibs/mchp/tests/reg_c/reg_c.v new file mode 100644 index 000000000..1d9ee0f32 --- /dev/null +++ b/techlibs/mchp/tests/reg_c/reg_c.v @@ -0,0 +1,122 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module reg_c( + input clk, + + // active high + input en_A, + input en_B, + input en_D, + input en_P, + + // active low + input srst_A, + input srst_B, + input srst_D, + input srst_P, + + // active low + input arst_D, + + input srst_C, + input arst_C, + + + input signed [5:0] in_A, + input signed [4:0] in_B, + input signed [4:0] in_C, + input signed [4:0] in_D, + + + output reg [11:0] out_P + +); + + +// MACC_PA takes active low resets +wire srst_A_N; +wire srst_B_N; +wire srst_C_N; +wire srst_D_N; +wire srst_P_N; +assign srst_A_N = ~srst_A; +assign srst_B_N = ~srst_B; +assign srst_C_N = ~srst_C; +assign srst_D_N = ~srst_D; +assign srst_P_N = ~srst_P; + +// input reg +reg signed [5:0] reg_A; +reg signed [4:0] reg_B; +reg signed [4:0] reg_C; +reg signed [4:0] reg_D; + +// sync reset A +always@(posedge clk) begin + // if (~srst_A_N) begin + if (srst_A_N) begin + reg_A = 6'b000000; + end else begin + reg_A = in_A; + end +end + + + +// sync reset B +always@(posedge clk) begin + if (srst_B_N) begin + reg_B = 5'b00000; + end else begin + reg_B = in_B; + end +end + + + +// async reset D +always@(posedge clk, negedge arst_D) begin + if (~arst_D) begin + reg_D = 5'b00000; + end else begin + reg_D = in_D; + end +end + +// sync reset C +always@(posedge clk) begin + if (srst_C_N) begin + reg_C = 5'b00000; + end else begin + reg_C = in_C; + end +end + + + +// sync reset P +always@(posedge clk) begin + if (srst_P_N) begin + out_P = 12'h000; + end else begin + out_P = reg_A * (reg_B + reg_D) + reg_C; + end +end + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/reg_c/reg_c.ys b/techlibs/mchp/tests/reg_c/reg_c.ys new file mode 100644 index 000000000..37c4df18d --- /dev/null +++ b/techlibs/mchp/tests/reg_c/reg_c.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog reg_c.v + +synth_mchp -top reg_c -abc9 -family pf -noiopad + +write_verilog -noexpr reg_c.vm diff --git a/techlibs/mchp/tests/reg_test/reg_test.v b/techlibs/mchp/tests/reg_test/reg_test.v new file mode 100644 index 000000000..dadec7ae8 --- /dev/null +++ b/techlibs/mchp/tests/reg_test/reg_test.v @@ -0,0 +1,97 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module reg_test( + input clk, + + // active high + input en_A, + input en_B, + input en_D, + input en_P, + + // active low + input srst_A, + input srst_B, + input srst_D, + input srst_P, + + // active low + input arst_D, + + input signed [5:0] in_A, + input signed [4:0] in_B, + input signed [4:0] in_D, + + output reg [11:0] out_P + +); + + +// MACC_PA takes active low resets +wire srst_A_N; +wire srst_B_N; +wire srst_D_N; +wire srst_P_N; +assign srst_A_N = ~srst_A; +assign srst_B_N = ~srst_B; +assign srst_D_N = ~srst_D; +assign srst_P_N = ~srst_P; + +// input reg +reg signed [5:0] reg_A; +reg signed [4:0] reg_B; +reg signed [4:0] reg_D; + +// sync reset A +always@(posedge clk) begin + if (srst_A_N) begin + reg_A = 6'b000000; + end else begin + reg_A = in_A; + end +end + +// sync reset B +always@(posedge clk) begin + if (srst_B_N) begin + reg_B = 5'b00000; + end else begin + reg_B = in_B; + end +end + +// async reset D +always@(posedge clk, negedge arst_D) begin + if (~arst_D) begin + reg_D = 5'b00000; + end else begin + reg_D = in_D; + end +end + +// sync reset P +always@(posedge clk) begin + if (srst_P_N) begin + out_P = 12'h000; + end else begin + out_P = reg_A * (reg_B + reg_D); + end +end + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/reg_test/reg_test.ys b/techlibs/mchp/tests/reg_test/reg_test.ys new file mode 100644 index 000000000..2c1fb87d7 --- /dev/null +++ b/techlibs/mchp/tests/reg_test/reg_test.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog reg_test.v + +synth_mchp -top reg_test -abc9 -family pf -noiopad + +write_verilog -noexpr reg_test.vm diff --git a/techlibs/mchp/tests/signed_mult/signed_mult.v b/techlibs/mchp/tests/signed_mult/signed_mult.v new file mode 100755 index 000000000..09d324af1 --- /dev/null +++ b/techlibs/mchp/tests/signed_mult/signed_mult.v @@ -0,0 +1,28 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module signed_mult( + input signed [17:0] in_A, + input signed [17:0] in_B, + + output signed [35:0] out_Y +); + +assign out_Y = in_A * in_B; + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/signed_mult/signed_mult.ys b/techlibs/mchp/tests/signed_mult/signed_mult.ys new file mode 100755 index 000000000..bba8cbfe2 --- /dev/null +++ b/techlibs/mchp/tests/signed_mult/signed_mult.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog signed_mult.v + +synth_mchp -top signed_mult -abc9 -family pf -noiopad + +write_verilog -noexpr signed_mult.vm diff --git a/techlibs/mchp/tests/simple_ram/simple_ram.v b/techlibs/mchp/tests/simple_ram/simple_ram.v new file mode 100644 index 000000000..5117b1b35 --- /dev/null +++ b/techlibs/mchp/tests/simple_ram/simple_ram.v @@ -0,0 +1,37 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module simple_ram (clk,wr,addr,din,dout); +input clk; +input [19:0] din; +input wr; +input [9:0] addr; +output [19:0] dout; + + +reg [9:0] addr_reg; +reg [19:0] mem [0:1023] ; +assign dout = mem[addr_reg]; + +always@(posedge clk) begin + addr_reg <= addr; + if(wr) + mem[addr]<= din; +end +endmodule + diff --git a/techlibs/mchp/tests/simple_ram/simple_ram.ys b/techlibs/mchp/tests/simple_ram/simple_ram.ys new file mode 100644 index 000000000..a315a2bfb --- /dev/null +++ b/techlibs/mchp/tests/simple_ram/simple_ram.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog simple_ram.v + +synth_mchp -top simple_ram -abc9 -family pf -noiopad + +write_verilog -noexpr simple_ram.vm diff --git a/techlibs/mchp/tests/unsigned_mult/unsigned_mult.v b/techlibs/mchp/tests/unsigned_mult/unsigned_mult.v new file mode 100644 index 000000000..987c77a37 --- /dev/null +++ b/techlibs/mchp/tests/unsigned_mult/unsigned_mult.v @@ -0,0 +1,28 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module unsigned_mult( + input [10:0] in_A, + input signed [10:0] in_B, + + output [21:0] out_Y +); + +assign out_Y = in_A * in_B; + +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/unsigned_mult/unsigned_mult.ys b/techlibs/mchp/tests/unsigned_mult/unsigned_mult.ys new file mode 100644 index 000000000..05118e265 --- /dev/null +++ b/techlibs/mchp/tests/unsigned_mult/unsigned_mult.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog unsigned_mult.v + +synth_mchp -top unsigned_mult -abc9 -family pf -noiopad + +write_verilog -noexpr unsigned_mult.vm diff --git a/techlibs/mchp/tests/uram_ar/uram_ar.v b/techlibs/mchp/tests/uram_ar/uram_ar.v new file mode 100644 index 000000000..524203c9b --- /dev/null +++ b/techlibs/mchp/tests/uram_ar/uram_ar.v @@ -0,0 +1,38 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module uram_ar(data,waddr,we,clk,q); +parameter d_width = 27; +parameter addr_width = 2; +parameter mem_depth = 4; +input [d_width-1:0] data; +input [addr_width-1:0] waddr; +input we, clk; +output [d_width-1:0] q; + +reg [d_width-1:0] mem [mem_depth-1:0]; + +assign q = mem[waddr]; + +always @(posedge clk) begin + if (we) + mem[waddr] <= data; + +end + +endmodule diff --git a/techlibs/mchp/tests/uram_ar/uram_ar.ys b/techlibs/mchp/tests/uram_ar/uram_ar.ys new file mode 100644 index 000000000..3650cb249 --- /dev/null +++ b/techlibs/mchp/tests/uram_ar/uram_ar.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog uram_ar.v + +synth_mchp -top uram_ar -abc9 -family pf -noiopad + +write_verilog -noexpr uram_ar.vm diff --git a/techlibs/mchp/tests/uram_sr/uram_sr.v b/techlibs/mchp/tests/uram_sr/uram_sr.v new file mode 100644 index 000000000..2bb588803 --- /dev/null +++ b/techlibs/mchp/tests/uram_sr/uram_sr.v @@ -0,0 +1,32 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module uram_sr(clk, wr, raddr, din, waddr, dout); +input clk; +input [11:0] din; +input wr; +input [5:0] waddr, raddr; +output [11:0] dout; +reg [5:0] raddr_reg; +reg [11:0] mem [0:63]; +assign dout = mem[raddr_reg]; +always@(posedge clk) begin + raddr_reg <= raddr; if(wr) + mem[waddr]<= din; +end +endmodule \ No newline at end of file diff --git a/techlibs/mchp/tests/uram_sr/uram_sr.ys b/techlibs/mchp/tests/uram_sr/uram_sr.ys new file mode 100644 index 000000000..a4c79398a --- /dev/null +++ b/techlibs/mchp/tests/uram_sr/uram_sr.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog uram_sr.v + +synth_mchp -top uram_sr -abc9 -family pf -noiopad + +write_verilog -noexpr uram_sr.vm diff --git a/techlibs/mchp/tests/widemux/widemux.v b/techlibs/mchp/tests/widemux/widemux.v new file mode 100644 index 000000000..1fe28ba28 --- /dev/null +++ b/techlibs/mchp/tests/widemux/widemux.v @@ -0,0 +1,48 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +module widemux( + input [3:0] data, + input S0, + input S1, + output Y + + ); + + wire A, B; + + always @ (*) begin + if (S0)begin + A = data[1]; + B = data[3]; + end else begin + A = data[0]; + B = data[2]; + end + + if (S1)begin + Y = A; + end else begin + Y = B; + end + + end +endmodule + + + diff --git a/techlibs/mchp/tests/widemux/widemux.ys b/techlibs/mchp/tests/widemux/widemux.ys new file mode 100644 index 000000000..f8aeaaa58 --- /dev/null +++ b/techlibs/mchp/tests/widemux/widemux.ys @@ -0,0 +1,21 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +read_verilog widemux.v + +synth_mchp -top widemux -abc9 -family pf -noiopad + +write_verilog -noexpr widemux.vm diff --git a/techlibs/mchp/uSRAM.txt b/techlibs/mchp/uSRAM.txt new file mode 100644 index 000000000..296fc8dd2 --- /dev/null +++ b/techlibs/mchp/uSRAM.txt @@ -0,0 +1,69 @@ +# ISC License +# +# Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# asynchronous read +ram block $__uSRAM_AR_ { + + #(LSRAM cost)/3 + cost 43; + + # INIT supported + init any; + + abits 6; + widths 12 per_port; + + # single write enable wire + port sw "W" { + clock posedge; + + # collision not supported, but write takes precedence and read data is invalid while writing to + # the same address + wrtrans all new; + + optional; + } + port ar "R" { + optional; + } +} + +# synchronous read +# NOTE: synchronous read can be realized by the address pipeline register or data pipeline register. +# This assumes address is synchronized +ram block $__uSRAM_SR_ { + + cost 42; + + init any; + abits 6; + widths 12 per_port; + + port sw "W" { + clock posedge; + + # collision not supported + wrtrans all new; + + optional; + } + port sr "R" { + clock posedge; + rden; + rdinit none; + optional; + } +} diff --git a/techlibs/mchp/uSRAM_map.v b/techlibs/mchp/uSRAM_map.v new file mode 100644 index 000000000..9fce7193c --- /dev/null +++ b/techlibs/mchp/uSRAM_map.v @@ -0,0 +1,118 @@ +/* +ISC License + +Copyright (C) 2024 Microchip Technology Inc. and its subsidiaries + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +// See document PolarFire Family Fabric User Guide +// section 4.2 for port list. + +// Asynchronous read +module $__uSRAM_AR_ (...); + +parameter INIT = 0; +parameter ADDR_BITS = 6; + +parameter PORT_W_WIDTH = 12; +parameter PORT_R_WIDTH = 12; +parameter PORT_R_USED = 0; +parameter PORT_W_USED = 0; + +input PORT_W_CLK; +input [ADDR_BITS-1:0] PORT_W_ADDR; +input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA; +input PORT_W_WR_EN; + +input [ADDR_BITS-1:0] PORT_R_ADDR; +output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA; + +RAM64x12 _TECHMAP_REPLACE_ ( + .R_ADDR(PORT_R_ADDR), + .R_ADDR_BYPASS(1'b1), + .R_ADDR_EN(1'b0), + .R_ADDR_SL_N(1'b1), + .R_ADDR_SD(1'b0), + .R_ADDR_AL_N(1'b1), + .R_ADDR_AD_N(1'b0), + .BLK_EN(PORT_R_USED ? 1'b1 : 1'b0), + .R_DATA(PORT_R_RD_DATA), + .R_DATA_BYPASS(1'b1), + .R_DATA_EN(1'b0), + .R_DATA_SL_N(1'b1), + .R_DATA_SD(1'b0), + .R_DATA_AL_N(1'b1), + .R_DATA_AD_N(1'b0), + + .W_CLK(PORT_W_CLK), + .W_ADDR(PORT_W_ADDR), + .W_DATA(PORT_W_WR_DATA), + .W_EN(PORT_W_WR_EN), + + .BUSY_FB(1'b0) +); + +endmodule + +// Synchronous read +module $__uSRAM_SR_ (...); + +parameter INIT = 0; +parameter ADDR_BITS = 6; + +parameter PORT_W_WIDTH = 12; +parameter PORT_R_WIDTH = 12; +parameter PORT_R_USED = 0; +parameter PORT_W_USED = 0; + +input PORT_W_CLK; +input [ADDR_BITS-1:0] PORT_W_ADDR; +input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA; +input PORT_W_WR_EN; + +// Read port clock and enable signal +// that async read uSRAM doesn't have +input PORT_R_CLK; +input PORT_R_RD_EN; +input [ADDR_BITS-1:0] PORT_R_ADDR; +output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA; + +RAM64x12 _TECHMAP_REPLACE_ ( + .R_CLK(PORT_R_CLK), + .R_ADDR(PORT_R_ADDR), + .R_ADDR_BYPASS(1'b0), + .R_ADDR_EN(PORT_R_RD_EN), + .R_ADDR_SL_N(1'b1), + .R_ADDR_SD(1'b0), + .R_ADDR_AL_N(1'b1), + .R_ADDR_AD_N(1'b0), + .BLK_EN(PORT_R_USED ? 1'b1 : 1'b0), + .R_DATA(PORT_R_RD_DATA), + .R_DATA_BYPASS(1'b1), + .R_DATA_EN(1'b0), + .R_DATA_SL_N(1'b1), + .R_DATA_SD(1'b0), + .R_DATA_AL_N(1'b1), + .R_DATA_AD_N(1'b0), + + .W_CLK(PORT_W_CLK), + .W_ADDR(PORT_W_ADDR), + .W_DATA(PORT_W_WR_DATA), + .W_EN(PORT_W_WR_EN), + + .BUSY_FB(1'b0) +); + +endmodule +