mirror of
https://github.com/openXC7/prjxray.git
synced 2026-08-22 14:06:54 +02:00
xc7series: refactor Part()
ConfigurationFrameAddress row-half and row fields translate directly to
the clock region structure used in 7-series parts. Break these concepts
out into separate classes and encode them as such in Part YAML.
Columns within a row are more complicated. Column indices are relative
to a BlockType. Think of each BlockType as a data bus that terminates at
some particular tile type (e.g. CLB_IO_CLK maps to INT_{L,R} tiles).
Column indices act as addresses of endpoints on the associated BlockType
bus. As the bus is 1 frame (101 words, 404 bytes) wide, each endpoint
feeds frames into multiple tiles simultaneously.
Minor addresses are frame addresses within a BlockType bus endpoint.
These can refer to frames either stored within the endpoint tiles
or in tiles chained behind them.
Note that a given tile can be connected on multiple BlockType buses.
For example, block RAMs appear to be attached both by being chained
behind an INT_{L,R} on the CLB_IO_CLK bus as well as being a direct
endpoint on the BLOCK_RAM bus. Due to this, tiles conceptually belong
to the row rather than a single column.
Signed-off-by: Rick Altherr <[email protected]>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
#include <prjxray/xilinx/xc7series/configuration_bus.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace prjxray {
|
||||
namespace xilinx {
|
||||
namespace xc7series {
|
||||
|
||||
bool ConfigurationBus::IsValidFrameAddress(FrameAddress address) const {
|
||||
auto addr_column = configuration_columns_.find(address.column());
|
||||
if (addr_column == configuration_columns_.end())
|
||||
return false;
|
||||
|
||||
return addr_column->second.IsValidFrameAddress(address);
|
||||
}
|
||||
|
||||
absl::optional<FrameAddress> ConfigurationBus::GetNextFrameAddress(
|
||||
FrameAddress address) const {
|
||||
// Find the column for the current address.
|
||||
auto addr_column = configuration_columns_.find(address.column());
|
||||
|
||||
// If the current address isn't in a known column, no way to know the
|
||||
// next address.
|
||||
if (addr_column == configuration_columns_.end())
|
||||
return {};
|
||||
|
||||
// Ask the column for the next address.
|
||||
absl::optional<FrameAddress> next_address =
|
||||
addr_column->second.GetNextFrameAddress(address);
|
||||
if (next_address)
|
||||
return next_address;
|
||||
|
||||
// The current column doesn't know what the next address is. Assume
|
||||
// that the next valid address is the beginning of the next column.
|
||||
if (++addr_column != configuration_columns_.end()) {
|
||||
auto next_address = FrameAddress(
|
||||
address.block_type(), address.is_bottom_half_rows(),
|
||||
address.row(), addr_column->first, 0);
|
||||
if (addr_column->second.IsValidFrameAddress(next_address))
|
||||
return next_address;
|
||||
}
|
||||
|
||||
// Not in this bus.
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace xc7series
|
||||
} // namespace xilinx
|
||||
} // namespace prjxray
|
||||
|
||||
namespace xc7series = prjxray::xilinx::xc7series;
|
||||
|
||||
namespace YAML {
|
||||
|
||||
Node convert<xc7series::ConfigurationBus>::encode(
|
||||
const xc7series::ConfigurationBus& rhs) {
|
||||
Node node;
|
||||
node.SetTag("xilinx/xc7series/configuration_bus");
|
||||
node["configuration_columns"] = rhs.configuration_columns_;
|
||||
return node;
|
||||
}
|
||||
|
||||
bool convert<xc7series::ConfigurationBus>::decode(
|
||||
const Node& node,
|
||||
xc7series::ConfigurationBus& lhs) {
|
||||
if (!node.Tag().empty() &&
|
||||
node.Tag() != "xilinx/xc7series/configuration_bus") {
|
||||
return false;
|
||||
}
|
||||
|
||||
lhs.configuration_columns_ =
|
||||
node["configuration_columns"]
|
||||
.as<std::map<unsigned int, xc7series::ConfigurationColumn>>();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace YAML
|
||||
Reference in New Issue
Block a user