Skip to content

Commit d9d0d38

Browse files
committed
Move common code to fpga_interchange_arch_utils
Signed-off-by: Maciej Dudek <[email protected]>
1 parent 9a5d200 commit d9d0d38

File tree

6 files changed

+308
-302
lines changed

6 files changed

+308
-302
lines changed

libs/libarchfpga/src/fpga_interchange_arch_utils.cpp

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,29 @@ float get_corner_value(DeviceResources::Device::CornerModel::Reader model, const
7777
return 0.;
7878
}
7979

80-
void fill_switch(t_rr_switch_inf& switch_,
80+
char* int_to_string(char* buff, int value) {
81+
if (value < 10) {
82+
return &(*buff = '0' + value) + 1;
83+
} else {
84+
return &(*int_to_string(buff, value / 10) = '0' + value % 10) + 1;
85+
}
86+
}
87+
88+
void pip_types(std::set<std::tuple<int, bool>>& seen,
89+
DeviceResources::Device::Reader ar_) {
90+
for (const auto& tile : ar_.getTileTypeList()) {
91+
for (const auto& pip : tile.getPips()) {
92+
if (pip.isPseudoCells())
93+
continue;
94+
seen.emplace(pip.getTiming(), pip.getBuffered21());
95+
if (!pip.getDirectional()) {
96+
seen.emplace(pip.getTiming(), pip.getBuffered20());
97+
}
98+
}
99+
}
100+
}
101+
102+
void fill_switch(t_arch_switch_inf* switch_,
81103
float R,
82104
float Cin,
83105
float Cout,
@@ -87,13 +109,73 @@ void fill_switch(t_rr_switch_inf& switch_,
87109
float buf_size,
88110
char* name,
89111
SwitchType type) {
90-
switch_.R = R;
91-
switch_.Cin = Cin;
92-
switch_.Cout = Cout;
93-
switch_.Cinternal = Cinternal;
94-
switch_.Tdel = Tdel;
95-
switch_.mux_trans_size = mux_trans_size;
96-
switch_.buf_size = buf_size;
97-
switch_.name = name;
98-
switch_.set_type(type);
112+
switch_->R = R;
113+
switch_->Cin = Cin;
114+
switch_->Cout = Cout;
115+
switch_->Cinternal = Cinternal;
116+
switch_->set_Tdel(t_arch_switch_inf::UNDEFINED_FANIN, Tdel);
117+
switch_->mux_trans_size = mux_trans_size;
118+
switch_->buf_size = buf_size;
119+
switch_->name = name;
120+
switch_->set_type(type);
121+
}
122+
123+
void process_cell_bel_mappings(DeviceResources::Device::Reader ar_,
124+
std::unordered_map<uint32_t, std::set<t_bel_cell_mapping>>& bel_cell_mappings_,
125+
std::function<std::string(size_t)> str) {
126+
auto primLib = ar_.getPrimLibs();
127+
auto portList = primLib.getPortList();
128+
129+
for (auto cell_mapping : ar_.getCellBelMap()) {
130+
size_t cell_name = cell_mapping.getCell();
131+
132+
int found_valid_prim = false;
133+
for (auto primitive : primLib.getCellDecls()) {
134+
bool is_prim = str(primitive.getLib()) == std::string("primitives");
135+
bool is_cell = cell_name == primitive.getName();
136+
137+
bool has_inout = false;
138+
for (auto port_idx : primitive.getPorts()) {
139+
auto port = portList[port_idx];
140+
141+
if (port.getDir() == INOUT) {
142+
has_inout = true;
143+
break;
144+
}
145+
}
146+
147+
if (is_prim && is_cell && !has_inout) {
148+
found_valid_prim = true;
149+
break;
150+
}
151+
}
152+
153+
if (!found_valid_prim)
154+
continue;
155+
156+
for (auto common_pins : cell_mapping.getCommonPins()) {
157+
std::vector<std::pair<size_t, size_t>> pins;
158+
159+
for (auto pin_map : common_pins.getPins())
160+
pins.emplace_back(pin_map.getCellPin(), pin_map.getBelPin());
161+
162+
for (auto site_type_entry : common_pins.getSiteTypes()) {
163+
size_t site_type = site_type_entry.getSiteType();
164+
165+
for (auto bel : site_type_entry.getBels()) {
166+
t_bel_cell_mapping mapping;
167+
168+
mapping.cell = cell_name;
169+
mapping.site = site_type;
170+
mapping.pins = pins;
171+
172+
std::set<t_bel_cell_mapping> maps{mapping};
173+
auto res = bel_cell_mappings_.emplace(bel, maps);
174+
if (!res.second) {
175+
res.first->second.insert(mapping);
176+
}
177+
}
178+
}
179+
}
180+
}
99181
}

libs/libarchfpga/src/fpga_interchange_arch_utils.h

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,39 @@
22
#define FPGAINTERCHANGE_ARCH_UTILS_FILE_H
33

44
#include "arch_types.h"
5+
#include "arch_util.h"
56
#include "arch_error.h"
67
#include "vtr_error.h"
8+
#include "vtr_util.h"
79

810
#include "DeviceResources.capnp.h"
911
#include "LogicalNetlist.capnp.h"
1012
#include "capnp/serialize.h"
1113
#include "capnp/serialize-packed.h"
1214
#include <fcntl.h>
1315
#include <unistd.h>
16+
#include <set>
17+
#include <string>
1418

1519
#ifdef __cplusplus
1620
extern "C" {
1721
#endif
1822

23+
// Necessary to reduce code verbosity when getting the pin directions
24+
static const auto INPUT = LogicalNetlist::Netlist::Direction::INPUT;
25+
static const auto OUTPUT = LogicalNetlist::Netlist::Direction::OUTPUT;
26+
static const auto INOUT = LogicalNetlist::Netlist::Direction::INOUT;
27+
28+
struct t_bel_cell_mapping {
29+
size_t cell;
30+
size_t site;
31+
std::vector<std::pair<size_t, size_t>> pins;
32+
33+
bool operator<(const t_bel_cell_mapping& other) const {
34+
return cell < other.cell || (cell == other.cell && site < other.site);
35+
}
36+
};
37+
1938
/****************** Utility functions ******************/
2039

2140
/**
@@ -34,7 +53,20 @@ extern "C" {
3453

3554
float get_corner_value(DeviceResources::Device::CornerModel::Reader model, const char* speed_model, const char* value);
3655

37-
void fill_switch(t_rr_switch_inf& switch_,
56+
char* int_to_string(char* buff, int value);
57+
58+
void pip_types(std::set<std::tuple<int, bool>>& seen,
59+
DeviceResources::Device::Reader ar_);
60+
61+
void process_cell_bel_mappings(DeviceResources::Device::Reader ar_,
62+
std::unordered_map<uint32_t, std::set<t_bel_cell_mapping>>& bel_cell_mappings_,
63+
std::function<std::string(size_t)> str);
64+
65+
#ifdef __cplusplus
66+
}
67+
#endif
68+
template<typename T>
69+
void fill_switch(T* switch_,
3870
float R,
3971
float Cin,
4072
float Cout,
@@ -45,8 +77,22 @@ void fill_switch(t_rr_switch_inf& switch_,
4577
char* name,
4678
SwitchType type);
4779

48-
#ifdef __cplusplus
49-
}
50-
#endif
80+
void fill_switch(t_arch_switch_inf* switch_,
81+
float R,
82+
float Cin,
83+
float Cout,
84+
float Cinternal,
85+
float Tdel,
86+
float mux_trans_size,
87+
float buf_size,
88+
char* name,
89+
SwitchType type);
90+
91+
template<typename T1, typename T2>
92+
void process_switches_array(DeviceResources::Device::Reader ar_,
93+
std::set<std::tuple<int, bool>>& seen,
94+
T1 switch_array,
95+
std::vector<std::tuple<std::tuple<int, bool>, int>>& pips_models_);
5196

97+
#include "fpga_interchange_arch_utils.impl.h"
5298
#endif
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/****************** Utility functions ******************/
2+
3+
/**
4+
* @brief The FPGA interchange timing model includes three different corners (min, typ and max) for each of the two
5+
* speed_models (slow and fast).
6+
*
7+
* Timing data can be found on PIPs, nodes, site pins and bel pins.
8+
* This function retrieves the timing value based on the wanted speed model and the wanted corner.
9+
*
10+
* Corner model is considered valid if at least one configuration is set.
11+
* In that case this value shall be returned.
12+
*
13+
* More information on the FPGA Interchange timing model can be found here:
14+
* - https://github.com/chipsalliance/fpga-interchange-schema/blob/main/interchange/DeviceResources.capnp
15+
*/
16+
17+
template<typename T>
18+
void fill_switch(T* switch_,
19+
float R,
20+
float Cin,
21+
float Cout,
22+
float Cinternal,
23+
float Tdel,
24+
float mux_trans_size,
25+
float buf_size,
26+
char* name,
27+
SwitchType type) {
28+
switch_->R = R;
29+
switch_->Cin = Cin;
30+
switch_->Cout = Cout;
31+
switch_->Cinternal = Cinternal;
32+
switch_->Tdel = Tdel;
33+
switch_->mux_trans_size = mux_trans_size;
34+
switch_->buf_size = buf_size;
35+
switch_->name = name;
36+
switch_->set_type(type);
37+
}
38+
39+
template<typename T1, typename T2>
40+
void process_switches_array(DeviceResources::Device::Reader ar_,
41+
std::set<std::tuple<int, bool>>& seen,
42+
T1 switch_array,
43+
std::vector<std::tuple<std::tuple<int, bool> ,int>>& pips_models_) {
44+
45+
fill_switch(&switch_array[T2(0)], 0, 0, 0, 0, 0, 0, 0,
46+
vtr::strdup("short"), SwitchType::SHORT);
47+
fill_switch(&switch_array[T2(1)], 0, 0, 0, 0, 0, 0, 0,
48+
vtr::strdup("generic"), SwitchType::MUX);
49+
50+
const auto& pip_models = ar_.getPipTimings();
51+
float R, Cin, Cout, Cint, Tdel;
52+
std::string switch_name;
53+
SwitchType type;
54+
int id =2;
55+
for (const auto& value : seen) {
56+
int timing_model_id;
57+
int mux_trans_size;
58+
bool buffered;
59+
std::tie(timing_model_id, buffered) = value;
60+
const auto& model = pip_models[timing_model_id];
61+
pips_models_.emplace_back(std::make_tuple(value, id));
62+
63+
R = Cin = Cint = Cout = Tdel = 0.0;
64+
std::stringstream name;
65+
std::string mux_type_string = buffered ? "mux_" : "passGate_";
66+
name << mux_type_string;
67+
68+
R = get_corner_value(model.getOutputResistance(), "slow", "min");
69+
name << "R" << std::scientific << R;
70+
71+
Cin = get_corner_value(model.getInputCapacitance(), "slow", "min");
72+
name << "Cin" << std::scientific << Cin;
73+
74+
Cout = get_corner_value(model.getOutputCapacitance(), "slow", "min");
75+
name << "Cout" << std::scientific << Cout;
76+
77+
if (buffered) {
78+
Cint = get_corner_value(model.getInternalCapacitance(), "slow", "min");
79+
name << "Cinternal" << std::scientific << Cint;
80+
}
81+
82+
Tdel = get_corner_value(model.getInternalDelay(), "slow", "min");
83+
name << "Tdel" << std::scientific << Tdel;
84+
85+
switch_name = name.str();
86+
type = buffered ? SwitchType::MUX : SwitchType::PASS_GATE;
87+
mux_trans_size = buffered ? 1 : 0;
88+
89+
fill_switch(&switch_array[T2(id)], R, Cin, Cout, Cint, Tdel,
90+
mux_trans_size, 0, vtr::strdup(switch_name.c_str()), type);
91+
92+
id++;
93+
}
94+
}

0 commit comments

Comments
 (0)