-
Notifications
You must be signed in to change notification settings - Fork 415
FPGA interchange: add RR graph generation #1999
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
acomodi
wants to merge
19
commits into
verilog-to-routing:master
Choose a base branch
from
antmicro:acom/fpga-interchange-rr-graph+constants
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 18 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
46af2d1
Initial FPGA Interchange rr_graph builder
mtdudek 8dec6b0
RR_graph building for fpga interchange
mtdudek b3bc567
Small bug fixes
mtdudek eab6266
Fixes in rr graph generation
mtdudek 7fc76c6
Fix unit test as testarch has 2 lut bels
mtdudek 17298bc
Get Xilinx 7 series to work
mtdudek ceaf604
Reducing rr_node and rr_edge count in fpga_interchange node translati…
mtdudek 96a2520
Add support for constant networks
mtdudek eb17d62
Format code
mtdudek 6135e8f
Squashed 'libs/EXTERNAL/libinterchange/' changes from 53e3feda4..54f6…
mtdudek 4153d2b
Misc fixes and comments
mtdudek 5bc078d
Move common code to fpga_interchange_arch_utils
mtdudek 94d2164
vpr: interchange: rr graph: use only routing segments
acomodi 09c771c
interchange: rr graph: adapt to use new RR graph library
acomodi 9264618
interchange: rr graph: cleaning code and adding comments
acomodi 59a0c7e
interchange: arch: add alternative sites types
mtdudek b7745fd
interchange: fix alternative sites
mtdudek f2ae4e5
run make format
acomodi cc10573
Add comments
mtdudek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
#include "fpga_interchange_arch_utils.h" | ||
|
||
/****************** Utility functions ******************/ | ||
|
||
/** | ||
* @brief The FPGA interchange timing model includes three different corners (min, typ and max) for each of the two | ||
* speed_models (slow and fast). | ||
* | ||
* Timing data can be found on PIPs, nodes, site pins and bel pins. | ||
* This function retrieves the timing value based on the wanted speed model and the wanted corner. | ||
* | ||
* Corner model is considered valid if at least one configuration is set. | ||
* In that case this value shall be returned. | ||
* | ||
* More information on the FPGA Interchange timing model can be found here: | ||
* - https://github.com/chipsalliance/fpga-interchange-schema/blob/main/interchange/DeviceResources.capnp | ||
*/ | ||
|
||
float get_corner_value(DeviceResources::Device::CornerModel::Reader model, const char* speed_model, const char* value) { | ||
bool slow_model = std::string(speed_model) == std::string("slow"); | ||
bool fast_model = std::string(speed_model) == std::string("fast"); | ||
|
||
bool min_corner = std::string(value) == std::string("min"); | ||
bool typ_corner = std::string(value) == std::string("typ"); | ||
bool max_corner = std::string(value) == std::string("max"); | ||
|
||
if (!slow_model && !fast_model) { | ||
archfpga_throw("", __LINE__, "Wrong speed model `%s`. Expected `slow` or `fast`\n", speed_model); | ||
} | ||
|
||
if (!min_corner && !typ_corner && !max_corner) { | ||
archfpga_throw("", __LINE__, "Wrong corner model `%s`. Expected `min`, `typ` or `max`\n", value); | ||
} | ||
|
||
bool has_fast = model.getFast().hasFast(); | ||
bool has_slow = model.getSlow().hasSlow(); | ||
|
||
if ((slow_model || (fast_model && !has_fast)) && has_slow) { | ||
auto half = model.getSlow().getSlow(); | ||
if (min_corner && half.getMin().isMin()) { | ||
return half.getMin().getMin(); | ||
} else if (typ_corner && half.getTyp().isTyp()) { | ||
return half.getTyp().getTyp(); | ||
} else if (max_corner && half.getMax().isMax()) { | ||
return half.getMax().getMax(); | ||
} else { | ||
if (half.getMin().isMin()) { | ||
return half.getMin().getMin(); | ||
} else if (half.getTyp().isTyp()) { | ||
return half.getTyp().getTyp(); | ||
} else if (half.getMax().isMax()) { | ||
return half.getMax().getMax(); | ||
} else { | ||
archfpga_throw("", __LINE__, "Invalid speed model %s. No value found!\n", speed_model); | ||
} | ||
} | ||
} else if ((fast_model || slow_model) && has_fast) { | ||
auto half = model.getFast().getFast(); | ||
if (min_corner && half.getMin().isMin()) { | ||
return half.getMin().getMin(); | ||
} else if (typ_corner && half.getTyp().isTyp()) { | ||
return half.getTyp().getTyp(); | ||
} else if (max_corner && half.getMax().isMax()) { | ||
return half.getMax().getMax(); | ||
} else { | ||
if (half.getMin().isMin()) { | ||
return half.getMin().getMin(); | ||
} else if (half.getTyp().isTyp()) { | ||
return half.getTyp().getTyp(); | ||
} else if (half.getMax().isMax()) { | ||
return half.getMax().getMax(); | ||
} else { | ||
archfpga_throw("", __LINE__, "Invalid speed model %s. No value found!\n", speed_model); | ||
} | ||
} | ||
} | ||
return 0.; | ||
} | ||
|
||
char* int_to_string(char* buff, int value) { | ||
if (value < 10) { | ||
return &(*buff = '0' + value) + 1; | ||
} else { | ||
return &(*int_to_string(buff, value / 10) = '0' + value % 10) + 1; | ||
} | ||
} | ||
|
||
void pip_types(std::set<std::tuple<int, bool>>& seen, | ||
DeviceResources::Device::Reader ar_) { | ||
for (const auto& tile : ar_.getTileTypeList()) { | ||
for (const auto& pip : tile.getPips()) { | ||
/* | ||
* FIXME | ||
* right now we allow for pseudo pips even tho we don't check if they are avaiable | ||
* if (pip.isPseudoCells()) | ||
* continue; | ||
*/ | ||
seen.emplace(pip.getTiming(), pip.getBuffered21()); | ||
if (!pip.getDirectional()) { | ||
seen.emplace(pip.getTiming(), pip.getBuffered20()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
void fill_switch(t_arch_switch_inf* switch_, | ||
float R, | ||
float Cin, | ||
float Cout, | ||
float Cinternal, | ||
float Tdel, | ||
float mux_trans_size, | ||
float buf_size, | ||
char* name, | ||
SwitchType type) { | ||
switch_->R = R; | ||
switch_->Cin = Cin; | ||
switch_->Cout = Cout; | ||
switch_->Cinternal = Cinternal; | ||
switch_->set_Tdel(t_arch_switch_inf::UNDEFINED_FANIN, Tdel); | ||
switch_->mux_trans_size = mux_trans_size; | ||
switch_->buf_size = buf_size; | ||
switch_->name = name; | ||
switch_->set_type(type); | ||
} | ||
|
||
void process_cell_bel_mappings(DeviceResources::Device::Reader ar_, | ||
std::unordered_map<uint32_t, std::set<t_bel_cell_mapping>>& bel_cell_mappings_, | ||
std::function<std::string(size_t)> str) { | ||
auto primLib = ar_.getPrimLibs(); | ||
auto portList = primLib.getPortList(); | ||
|
||
for (auto cell_mapping : ar_.getCellBelMap()) { | ||
size_t cell_name = cell_mapping.getCell(); | ||
|
||
int found_valid_prim = false; | ||
for (auto primitive : primLib.getCellDecls()) { | ||
if (cell_name != primitive.getName()) continue; | ||
if (str(primitive.getLib()) != std::string("primitives")) continue; | ||
|
||
bool has_inout = false; | ||
for (auto port_idx : primitive.getPorts()) { | ||
auto port = portList[port_idx]; | ||
|
||
if (port.getDir() == INOUT) { | ||
has_inout = true; | ||
break; | ||
} | ||
} | ||
|
||
if (!has_inout) { | ||
found_valid_prim = true; | ||
break; | ||
} | ||
} | ||
|
||
if (!found_valid_prim) | ||
continue; | ||
|
||
for (auto common_pins : cell_mapping.getCommonPins()) { | ||
std::vector<std::pair<size_t, size_t>> pins; | ||
|
||
for (auto pin_map : common_pins.getPins()) | ||
pins.emplace_back(pin_map.getCellPin(), pin_map.getBelPin()); | ||
|
||
for (auto site_type_entry : common_pins.getSiteTypes()) { | ||
size_t site_type = site_type_entry.getSiteType(); | ||
|
||
for (auto bel : site_type_entry.getBels()) { | ||
t_bel_cell_mapping mapping; | ||
|
||
mapping.cell = cell_name; | ||
mapping.site = site_type; | ||
mapping.pins = pins; | ||
|
||
std::set<t_bel_cell_mapping> maps{mapping}; | ||
auto res = bel_cell_mappings_.emplace(bel, maps); | ||
if (!res.second) { | ||
res.first->second.insert(mapping); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#ifndef FPGAINTERCHANGE_ARCH_UTILS_FILE_H | ||
#define FPGAINTERCHANGE_ARCH_UTILS_FILE_H | ||
|
||
#include "arch_types.h" | ||
#include "arch_util.h" | ||
#include "arch_error.h" | ||
#include "vtr_error.h" | ||
#include "vtr_util.h" | ||
|
||
#include "DeviceResources.capnp.h" | ||
#include "LogicalNetlist.capnp.h" | ||
#include "capnp/serialize.h" | ||
#include "capnp/serialize-packed.h" | ||
#include <fcntl.h> | ||
#include <unistd.h> | ||
#include <set> | ||
#include <string> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
// Necessary to reduce code verbosity when getting the pin directions | ||
static const auto INPUT = LogicalNetlist::Netlist::Direction::INPUT; | ||
static const auto OUTPUT = LogicalNetlist::Netlist::Direction::OUTPUT; | ||
static const auto INOUT = LogicalNetlist::Netlist::Direction::INOUT; | ||
|
||
struct t_bel_cell_mapping { | ||
size_t cell; | ||
size_t site; | ||
std::vector<std::pair<size_t, size_t>> pins; | ||
|
||
bool operator<(const t_bel_cell_mapping& other) const { | ||
return cell < other.cell || (cell == other.cell && site < other.site); | ||
} | ||
}; | ||
|
||
/****************** Utility functions ******************/ | ||
|
||
/** | ||
* @brief The FPGA interchange timing model includes three different corners (min, typ and max) for each of the two | ||
* speed_models (slow and fast). | ||
* | ||
* Timing data can be found on PIPs, nodes, site pins and bel pins. | ||
* This function retrieves the timing value based on the wanted speed model and the wanted corner. | ||
* | ||
* Corner model is considered valid if at least one configuration is set. | ||
* In that case this value shall be returned. | ||
* | ||
* More information on the FPGA Interchange timing model can be found here: | ||
* - https://github.com/chipsalliance/fpga-interchange-schema/blob/main/interchange/DeviceResources.capnp | ||
*/ | ||
|
||
float get_corner_value(DeviceResources::Device::CornerModel::Reader model, const char* speed_model, const char* value); | ||
|
||
char* int_to_string(char* buff, int value); | ||
|
||
void pip_types(std::set<std::tuple<int, bool>>& seen, | ||
DeviceResources::Device::Reader ar_); | ||
|
||
void process_cell_bel_mappings(DeviceResources::Device::Reader ar_, | ||
std::unordered_map<uint32_t, std::set<t_bel_cell_mapping>>& bel_cell_mappings_, | ||
std::function<std::string(size_t)> str); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
template<typename T> | ||
void fill_switch(T* switch_, | ||
float R, | ||
float Cin, | ||
float Cout, | ||
float Cinternal, | ||
float Tdel, | ||
float mux_trans_size, | ||
float buf_size, | ||
char* name, | ||
SwitchType type); | ||
|
||
void fill_switch(t_arch_switch_inf* switch_, | ||
float R, | ||
float Cin, | ||
float Cout, | ||
float Cinternal, | ||
float Tdel, | ||
float mux_trans_size, | ||
float buf_size, | ||
char* name, | ||
SwitchType type); | ||
|
||
template<typename T1, typename T2> | ||
void process_switches_array(DeviceResources::Device::Reader ar_, | ||
std::set<std::tuple<int, bool>>& seen, | ||
T1 switch_array, | ||
std::vector<std::tuple<std::tuple<int, bool>, int>>& pips_models_); | ||
|
||
#include "fpga_interchange_arch_utils.impl.h" | ||
#endif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you use template here to be compatible with
t_switch_inf
andt_rr_switch_inf
. Maybe it is better to note in code comments for developers.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add comment that
process_switches_array()
is template function.