diff options
Diffstat (limited to 'gowin/arch.h')
-rw-r--r-- | gowin/arch.h | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/gowin/arch.h b/gowin/arch.h new file mode 100644 index 00000000..05c9e125 --- /dev/null +++ b/gowin/arch.h @@ -0,0 +1,436 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Claire Wolf <claire@symbioticeda.com> + * Copyright (C) 2020 Pepijn de Vos <pepijn@symbioticeda.com> + * + * 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. + * + */ + +#ifndef NEXTPNR_H +#error Include "arch.h" via "nextpnr.h" only. +#endif + +NEXTPNR_NAMESPACE_BEGIN + +template <typename T> struct RelPtr +{ + int32_t offset; + + // void set(const T *ptr) { + // offset = reinterpret_cast<const char*>(ptr) - + // reinterpret_cast<const char*>(this); + // } + + const T *get() const { return reinterpret_cast<const T *>(reinterpret_cast<const char *>(this) + offset); } + + T *get_mut() const { return const_cast<T *>(reinterpret_cast<const T *>(reinterpret_cast<const char *>(this) + offset)); } + + const T &operator[](size_t index) const { return get()[index]; } + + const T &operator*() const { return *(get()); } + + const T *operator->() const { return get(); } + + RelPtr(const RelPtr &) = delete; + RelPtr &operator=(const RelPtr &) = delete; +}; + +NPNR_PACKED_STRUCT(struct PairPOD { + uint16_t dest_id; + uint16_t src_id; +}); + +NPNR_PACKED_STRUCT(struct BelsPOD { + uint16_t type_id; + uint16_t num_ports; + RelPtr<PairPOD> ports; +}); + +NPNR_PACKED_STRUCT(struct TilePOD /*TidePOD*/ { + uint32_t num_bels; + RelPtr<BelsPOD> bels; + uint32_t num_pips; + RelPtr<PairPOD> pips; + uint32_t num_clock_pips; + RelPtr<PairPOD> clock_pips; + uint32_t num_aliases; + RelPtr<PairPOD> aliases; +}); + +NPNR_PACKED_STRUCT(struct GlobalAliasPOD { + uint16_t dest_row; + uint16_t dest_col; + uint16_t dest_id; + uint16_t src_row; + uint16_t src_col; + uint16_t src_id; +}); + +NPNR_PACKED_STRUCT(struct TimingPOD { + uint32_t name_id; + // input, output + uint32_t ff; + uint32_t fr; + uint32_t rf; + uint32_t rr; +}); + +NPNR_PACKED_STRUCT(struct TimingGroupPOD { + uint32_t name_id; + uint32_t num_timings; + RelPtr<TimingPOD> timings; +}); + +NPNR_PACKED_STRUCT(struct TimingGroupsPOD { + TimingGroupPOD lut; + TimingGroupPOD alu; + TimingGroupPOD sram; + TimingGroupPOD dff; + //TimingGroupPOD dl; + //TimingGroupPOD iddroddr; + //TimingGroupPOD pll; + //TimingGroupPOD dll; + TimingGroupPOD bram; + //TimingGroupPOD dsp; + TimingGroupPOD fanout; + TimingGroupPOD glbsrc; + TimingGroupPOD hclk; + TimingGroupPOD iodelay; + //TimingGroupPOD io; + //TimingGroupPOD iregoreg; + TimingGroupPOD wire; +}); + +NPNR_PACKED_STRUCT(struct TimingClassPOD { + uint32_t name_id; + uint32_t num_groups; + RelPtr<TimingGroupsPOD> groups; +}); + +NPNR_PACKED_STRUCT(struct PackagePOD { + uint32_t name_id; + uint32_t num_pins; + RelPtr<PairPOD> pins; +}); + +NPNR_PACKED_STRUCT(struct VariantPOD { + uint32_t name_id; + uint32_t num_packages; + RelPtr<PackagePOD> packages; +}); + +NPNR_PACKED_STRUCT(struct DatabasePOD { + RelPtr<char> family; + uint32_t version; + uint16_t rows; + uint16_t cols; + RelPtr<RelPtr<TilePOD>> grid; + uint32_t num_aliases; + RelPtr<GlobalAliasPOD> aliases; + uint32_t num_speeds; + RelPtr<TimingClassPOD> speeds; + uint32_t num_variants; + RelPtr<VariantPOD> variants; + uint16_t num_constids; + uint16_t num_ids; + RelPtr<RelPtr<char>> id_strs; +}); + +struct ArchArgs +{ + std::string device; + std::string family; + std::string speed; + std::string package; + // y = mx + c relationship between distance and delay for interconnect + // delay estimates + double delayScale = 0.4, delayOffset = 0.4; +}; + +struct WireInfo; + +struct PipInfo +{ + IdString name, type; + std::map<IdString, std::string> attrs; + NetInfo *bound_net; + WireId srcWire, dstWire; + DelayInfo delay; + DecalXY decalxy; + Loc loc; +}; + +struct WireInfo +{ + IdString name, type; + std::map<IdString, std::string> attrs; + NetInfo *bound_net; + std::vector<PipId> downhill, uphill; + BelPin uphill_bel_pin; + std::vector<BelPin> downhill_bel_pins; + std::vector<BelPin> bel_pins; + DecalXY decalxy; + int x, y; +}; + +struct PinInfo +{ + IdString name; + WireId wire; + PortType type; +}; + +struct BelInfo +{ + IdString name, type; + std::map<IdString, std::string> attrs; + CellInfo *bound_cell; + std::unordered_map<IdString, PinInfo> pins; + DecalXY decalxy; + int x, y, z; + bool gb; +}; + +struct GroupInfo +{ + IdString name; + std::vector<BelId> bels; + std::vector<WireId> wires; + std::vector<PipId> pips; + std::vector<GroupId> groups; + DecalXY decalxy; +}; + +struct CellDelayKey +{ + IdString from, to; + inline bool operator==(const CellDelayKey &other) const { return from == other.from && to == other.to; } +}; + +NEXTPNR_NAMESPACE_END +namespace std { +template <> struct hash<NEXTPNR_NAMESPACE_PREFIX CellDelayKey> +{ + std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX CellDelayKey &dk) const noexcept + { + std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.from); + seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.to) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } +}; +} // namespace std +NEXTPNR_NAMESPACE_BEGIN + +struct CellTiming +{ + std::unordered_map<IdString, TimingPortClass> portClasses; + std::unordered_map<CellDelayKey, DelayInfo> combDelays; + std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo; +}; + +struct Arch : BaseCtx +{ + std::string family; + std::string device; + const PackagePOD *package; + const TimingGroupsPOD *speed; + + std::unordered_map<IdString, WireInfo> wires; + std::unordered_map<IdString, PipInfo> pips; + std::unordered_map<IdString, BelInfo> bels; + std::unordered_map<GroupId, GroupInfo> groups; + + // These functions include useful errors if not found + WireInfo &wire_info(IdString wire); + PipInfo &pip_info(IdString wire); + BelInfo &bel_info(IdString wire); + + std::vector<IdString> bel_ids, wire_ids, pip_ids; + + std::unordered_map<Loc, BelId> bel_by_loc; + std::vector<std::vector<std::vector<BelId>>> bels_by_tile; + + std::unordered_map<DecalId, std::vector<GraphicElement>> decal_graphics; + + int gridDimX, gridDimY; + std::vector<std::vector<int>> tileBelDimZ; + std::vector<std::vector<int>> tilePipDimZ; + + std::unordered_map<IdString, CellTiming> cellTiming; + + void addWire(IdString name, IdString type, int x, int y); + void addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc); + + void addBel(IdString name, IdString type, Loc loc, bool gb); + void addBelInput(IdString bel, IdString name, IdString wire); + void addBelOutput(IdString bel, IdString name, IdString wire); + void addBelInout(IdString bel, IdString name, IdString wire); + + void addGroupBel(IdString group, IdString bel); + void addGroupWire(IdString group, IdString wire); + void addGroupPip(IdString group, IdString pip); + void addGroupGroup(IdString group, IdString grp); + + void addDecalGraphic(DecalId decal, const GraphicElement &graphic); + void setWireDecal(WireId wire, DecalXY decalxy); + void setPipDecal(PipId pip, DecalXY decalxy); + void setBelDecal(BelId bel, DecalXY decalxy); + void setGroupDecal(GroupId group, DecalXY decalxy); + + void setWireAttr(IdString wire, IdString key, const std::string &value); + void setPipAttr(IdString pip, IdString key, const std::string &value); + void setBelAttr(IdString bel, IdString key, const std::string &value); + + void setDelayScaling(double scale, double offset); + + void addCellTimingClock(IdString cell, IdString port); + void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay); + void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); + void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq); + + IdString wireToGlobal(int &row, int &col, const DatabasePOD* db, IdString &wire); + DelayInfo getWireTypeDelay(IdString wire); + void read_cst(std::istream &in); + + // --------------------------------------------------------------- + // Common Arch API. Every arch must provide the following methods. + + ArchArgs args; + Arch(ArchArgs args); + + std::string getChipName() const { return device; } + + IdString archId() const { return id("gowin"); } + ArchArgs archArgs() const { return args; } + IdString archArgsToId(ArchArgs args) const { return id("none"); } + + int getGridDimX() const { return gridDimX; } + int getGridDimY() const { return gridDimY; } + int getTileBelDimZ(int x, int y) const { return tileBelDimZ[x][y]; } + int getTilePipDimZ(int x, int y) const { return tilePipDimZ[x][y]; } + + BelId getBelByName(IdString name) const; + IdString getBelName(BelId bel) const; + Loc getBelLocation(BelId bel) const; + BelId getBelByLocation(Loc loc) const; + const std::vector<BelId> &getBelsByTile(int x, int y) const; + bool getBelGlobalBuf(BelId bel) const; + uint32_t getBelChecksum(BelId bel) const; + void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength); + void unbindBel(BelId bel); + bool checkBelAvail(BelId bel) const; + CellInfo *getBoundBelCell(BelId bel) const; + CellInfo *getConflictingBelCell(BelId bel) const; + const std::vector<BelId> &getBels() const; + IdString getBelType(BelId bel) const; + const std::map<IdString, std::string> &getBelAttrs(BelId bel) const; + WireId getBelPinWire(BelId bel, IdString pin) const; + PortType getBelPinType(BelId bel, IdString pin) const; + std::vector<IdString> getBelPins(BelId bel) const; + + WireId getWireByName(IdString name) const; + IdString getWireName(WireId wire) const; + IdString getWireType(WireId wire) const; + const std::map<IdString, std::string> &getWireAttrs(WireId wire) const; + uint32_t getWireChecksum(WireId wire) const; + void bindWire(WireId wire, NetInfo *net, PlaceStrength strength); + void unbindWire(WireId wire); + bool checkWireAvail(WireId wire) const; + NetInfo *getBoundWireNet(WireId wire) const; + WireId getConflictingWireWire(WireId wire) const { return wire; } + NetInfo *getConflictingWireNet(WireId wire) const; + DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); } + const std::vector<WireId> &getWires() const; + const std::vector<BelPin> &getWireBelPins(WireId wire) const; + + PipId getPipByName(IdString name) const; + IdString getPipName(PipId pip) const; + IdString getPipType(PipId pip) const; + const std::map<IdString, std::string> &getPipAttrs(PipId pip) const; + uint32_t getPipChecksum(PipId pip) const; + void bindPip(PipId pip, NetInfo *net, PlaceStrength strength); + void unbindPip(PipId pip); + bool checkPipAvail(PipId pip) const; + NetInfo *getBoundPipNet(PipId pip) const; + WireId getConflictingPipWire(PipId pip) const; + NetInfo *getConflictingPipNet(PipId pip) const; + const std::vector<PipId> &getPips() const; + Loc getPipLocation(PipId pip) const; + WireId getPipSrcWire(PipId pip) const; + WireId getPipDstWire(PipId pip) const; + DelayInfo getPipDelay(PipId pip) const; + const std::vector<PipId> &getPipsDownhill(WireId wire) const; + const std::vector<PipId> &getPipsUphill(WireId wire) const; + + GroupId getGroupByName(IdString name) const; + IdString getGroupName(GroupId group) const; + std::vector<GroupId> getGroups() const; + const std::vector<BelId> &getGroupBels(GroupId group) const; + const std::vector<WireId> &getGroupWires(GroupId group) const; + const std::vector<PipId> &getGroupPips(GroupId group) const; + const std::vector<GroupId> &getGroupGroups(GroupId group) const; + + delay_t estimateDelay(WireId src, WireId dst) const; + delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const; + delay_t getDelayEpsilon() const { return 0.01; } + delay_t getRipupDelayPenalty() const { return 0.4; } + float getDelayNS(delay_t v) const { return v; } + + DelayInfo getDelayFromNS(float ns) const + { + DelayInfo del; + del.maxRaise = ns; + del.maxFall = ns; + del.minRaise = ns; + del.minFall = ns; + return del; + } + + uint32_t getDelayChecksum(delay_t v) const { return 0; } + bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const; + + ArcBounds getRouteBoundingBox(WireId src, WireId dst) const; + + bool pack(); + bool place(); + bool route(); + + const std::vector<GraphicElement> &getDecalGraphics(DecalId decal) const; + DecalXY getBelDecal(BelId bel) const; + DecalXY getWireDecal(WireId wire) const; + DecalXY getPipDecal(PipId pip) const; + DecalXY getGroupDecal(GroupId group) const; + + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const; + // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port + TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const; + // Get the TimingClockingInfo of a port + TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const; + + bool isValidBelForCell(CellInfo *cell, BelId bel) const; + bool isBelLocationValid(BelId bel) const; + + static const std::string defaultPlacer; + static const std::vector<std::string> availablePlacers; + static const std::string defaultRouter; + static const std::vector<std::string> availableRouters; + + // --------------------------------------------------------------- + // Internal usage + void assignArchInfo(); + bool cellsCompatible(const CellInfo **cells, int count) const; +}; + +NEXTPNR_NAMESPACE_END |