diff --git a/.cirrus.yml b/.cirrus.yml index f7181fd3..b7ff1891 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -8,6 +8,7 @@ task: submodule_script: git submodule sync --recursive && git submodule update --init --recursive build_script: mkdir build && cd build && cmake .. -DARCH=all+alpha -DOXIDE_INSTALL_PREFIX=$HOME/.cargo -DBUILD_TESTS=on -DBUILD_GUI=on && make -j3 test_generic_script: cd build && ./nextpnr-generic-test + flow_test_generic_script: export NPNR=$(pwd)/build/nextpnr-generic && cd tests/generic/flow && ./run.sh test_ice40_script: cd build && ./nextpnr-ice40-test smoketest_ice40_script: export NEXTPNR=$(pwd)/build/nextpnr-ice40 && cd ice40/smoketest/attosoc && ./smoketest.sh test_ecp5_script: cd build && ./nextpnr-ecp5-test diff --git a/docs/generic.md b/docs/generic.md index 5ea4804d..5c079a7b 100644 --- a/docs/generic.md +++ b/docs/generic.md @@ -28,9 +28,9 @@ Adds a pip (programmable connection between two named wires). Pip delays that co Loc is constructed using `Loc(x, y, z)`. 'z' for pips is only important if region constraints (e.g. for partial reconfiguration regions) are used. -### void addBel(IdString name, IdString type, Loc loc, bool gb); +### void addBel(IdString name, IdString type, Loc loc, bool gb, bool hidden); -Adds a bel to the FPGA description. Bel type should match the type of cells in the netlist that are placed at this bel (see below for information on special bel types supported by the packer). Loc is constructed using `Loc(x, y, z)` and must be unique. +Adds a bel to the FPGA description. Bel type should match the type of cells in the netlist that are placed at this bel (see below for information on special bel types supported by the packer). Loc is constructed using `Loc(x, y, z)` and must be unique. If `hidden` is true, then the bel will not be included in utilisation reports (e.g. for routing/internal use bels). ### void addBelInput(IdString bel, IdString name, IdString wire); ### void addBelOutput(IdString bel, IdString name, IdString wire); @@ -90,6 +90,14 @@ Specify setup and hold timings for a port of a cell, and set the timing class of Specify clock-to-out time for a port of a cell, and set the timing class of that port as register output. +### void clearCellBelPinMap(IdString cell, IdString cell_pin); + +Remove all bel pin mappings from a given cell pin. + +### addCellBelPinMapping(IdString cell, IdString cell_pin, IdString bel_pin); + +Add a bel pin to the list of bel pins a cell pin maps to. Note that if no mappings are set up (the usual case), cell pins are assumed to map to an identically named bel pin. + ## Generic Packer The generic packer combines K-input LUTs (`LUT` cells) and simple D-type flip flops (`DFF` cells) (posedge clock only, no set/reset or enable) into a `GENERIC_SLICE` cell. It also inserts `GENERIC_IOB`s onto any top level IO pins without an IO buffer. Constrained IOBs can be implemented by instantiating `GENERIC_IOB` and setting the `BEL` attribute to an IO location. diff --git a/generic/arch.cc b/generic/arch.cc index 7cd71179..999e5033 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -249,6 +249,12 @@ void Arch::addCellTimingClockToOut(IdString cell, IdString port, IdString clock, cellTiming[cell].portClasses[port] = TMG_REGISTER_OUTPUT; } +void Arch::clearCellBelPinMap(IdString cell, IdString cell_pin) { cells.at(cell)->bel_pins[cell_pin].clear(); } +void Arch::addCellBelPinMapping(IdString cell, IdString cell_pin, IdString bel_pin) +{ + cells.at(cell)->bel_pins[cell_pin].push_back(bel_pin); +} + // --------------------------------------------------------------- Arch::Arch(ArchArgs args) : chipName("generic"), args(args) @@ -342,7 +348,10 @@ std::vector Arch::getBelPins(BelId bel) const return ret; } -std::array Arch::getBelPinsForCellPin(CellInfo *cell_info, IdString pin) const { return {pin}; } +const std::vector &Arch::getBelPinsForCellPin(CellInfo *cell_info, IdString pin) const +{ + return cell_info->bel_pins.at(pin); +} // --------------------------------------------------------------- @@ -694,6 +703,10 @@ void Arch::assignArchInfo() ci->is_slice = false; } ci->user_group = int_or_default(ci->attrs, id("PACK_GROUP"), -1); + // If no manual cell->bel pin rule has been created; assign a default one + for (auto &p : ci->ports) + if (!ci->bel_pins.count(p.first)) + ci->bel_pins.emplace(p.first, std::vector{p.first}); } } diff --git a/generic/arch.h b/generic/arch.h index 2a0c7158..007478eb 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -125,7 +125,7 @@ struct ArchRanges using TileBelsRangeT = const std::vector &; using BelAttrsRangeT = const std::map &; using BelPinsRangeT = std::vector; - using CellBelPinRangeT = std::array; + using CellBelPinRangeT = const std::vector &; // Wires using AllWiresRangeT = const std::vector &; using DownhillPipRangeT = const std::vector &; @@ -207,6 +207,9 @@ struct Arch : ArchAPI void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq); + void clearCellBelPinMap(IdString cell, IdString cell_pin); + void addCellBelPinMapping(IdString cell, IdString cell_pin, IdString bel_pin); + // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. @@ -244,7 +247,7 @@ struct Arch : ArchAPI WireId getBelPinWire(BelId bel, IdString pin) const override; PortType getBelPinType(BelId bel, IdString pin) const override; std::vector getBelPins(BelId bel) const override; - std::array getBelPinsForCellPin(CellInfo *cell_info, IdString pin) const override; + const std::vector &getBelPinsForCellPin(CellInfo *cell_info, IdString pin) const override; WireId getWireByName(IdStringList name) const override; IdStringList getWireName(WireId wire) const override; diff --git a/generic/arch_pybindings.cc b/generic/arch_pybindings.cc index 3dc04206..35ec3b33 100644 --- a/generic/arch_pybindings.cc +++ b/generic/arch_pybindings.cc @@ -226,6 +226,14 @@ void arch_wrap_python(py::module &m) pass_through>::def_wrap(ctx_cls, "addCellTimingClockToOut", "cell"_a, "port"_a, "clock"_a, "clktoq"_a); + fn_wrapper_2a_v, conv_from_str>::def_wrap(ctx_cls, "clearCellBelPinMap", "cell"_a, + "cell_pin"_a); + fn_wrapper_3a_v, conv_from_str, + conv_from_str>::def_wrap(ctx_cls, "addCellBelPinMapping", "cell"_a, "cell_pin"_a, + "bel_pin"_a); + // const\_range\ getBelBuckets() const fn_wrapper_0a &>>::def_wrap(ctx_cls, "getBelBuckets"); diff --git a/generic/archdefs.h b/generic/archdefs.h index fad36894..30503414 100644 --- a/generic/archdefs.h +++ b/generic/archdefs.h @@ -68,6 +68,8 @@ struct ArchCellInfo bool is_slice; // Only packing rule for slice type primitives is a single clock per tile const NetInfo *slice_clk; + // Cell to bel pin mapping + std::unordered_map> bel_pins; }; NEXTPNR_NAMESPACE_END diff --git a/tests b/tests index 31648368..7673d601 160000 --- a/tests +++ b/tests @@ -1 +1 @@ -Subproject commit 31648368460b9e216479ce7c38e6fed883c380c4 +Subproject commit 7673d60124707346de001367afcbab6be466f405