Skip to content

Commit 573f55e

Browse files
mtdudekacomodi
authored andcommitted
Move common code to fpga_interchange_arch_utils
Signed-off-by: Maciej Dudek <[email protected]>
1 parent ad2bdf4 commit 573f55e

6 files changed

+313
-303
lines changed

libs/libarchfpga/src/fpga_interchange_arch_utils.cpp

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,33 @@ 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+
/*
93+
* FIXME
94+
* right now we allow for pseudo pips even tho we don't check if they are avaiable
95+
* if (pip.isPseudoCells())
96+
* continue;
97+
*/
98+
seen.emplace(pip.getTiming(), pip.getBuffered21());
99+
if (!pip.getDirectional()) {
100+
seen.emplace(pip.getTiming(), pip.getBuffered20());
101+
}
102+
}
103+
}
104+
}
105+
106+
void fill_switch(t_arch_switch_inf* switch_,
81107
float R,
82108
float Cin,
83109
float Cout,
@@ -87,13 +113,73 @@ void fill_switch(t_rr_switch_inf& switch_,
87113
float buf_size,
88114
char* name,
89115
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);
116+
switch_->R = R;
117+
switch_->Cin = Cin;
118+
switch_->Cout = Cout;
119+
switch_->Cinternal = Cinternal;
120+
switch_->set_Tdel(t_arch_switch_inf::UNDEFINED_FANIN, Tdel);
121+
switch_->mux_trans_size = mux_trans_size;
122+
switch_->buf_size = buf_size;
123+
switch_->name = name;
124+
switch_->set_type(type);
125+
}
126+
127+
void process_cell_bel_mappings(DeviceResources::Device::Reader ar_,
128+
std::unordered_map<uint32_t, std::set<t_bel_cell_mapping>>& bel_cell_mappings_,
129+
std::function<std::string(size_t)> str) {
130+
auto primLib = ar_.getPrimLibs();
131+
auto portList = primLib.getPortList();
132+
133+
for (auto cell_mapping : ar_.getCellBelMap()) {
134+
size_t cell_name = cell_mapping.getCell();
135+
136+
int found_valid_prim = false;
137+
for (auto primitive : primLib.getCellDecls()) {
138+
bool is_prim = str(primitive.getLib()) == std::string("primitives");
139+
bool is_cell = cell_name == primitive.getName();
140+
141+
bool has_inout = false;
142+
for (auto port_idx : primitive.getPorts()) {
143+
auto port = portList[port_idx];
144+
145+
if (port.getDir() == INOUT) {
146+
has_inout = true;
147+
break;
148+
}
149+
}
150+
151+
if (is_prim && is_cell && !has_inout) {
152+
found_valid_prim = true;
153+
break;
154+
}
155+
}
156+
157+
if (!found_valid_prim)
158+
continue;
159+
160+
for (auto common_pins : cell_mapping.getCommonPins()) {
161+
std::vector<std::pair<size_t, size_t>> pins;
162+
163+
for (auto pin_map : common_pins.getPins())
164+
pins.emplace_back(pin_map.getCellPin(), pin_map.getBelPin());
165+
166+
for (auto site_type_entry : common_pins.getSiteTypes()) {
167+
size_t site_type = site_type_entry.getSiteType();
168+
169+
for (auto bel : site_type_entry.getBels()) {
170+
t_bel_cell_mapping mapping;
171+
172+
mapping.cell = cell_name;
173+
mapping.site = site_type;
174+
mapping.pins = pins;
175+
176+
std::set<t_bel_cell_mapping> maps{mapping};
177+
auto res = bel_cell_mappings_.emplace(bel, maps);
178+
if (!res.second) {
179+
res.first->second.insert(mapping);
180+
}
181+
}
182+
}
183+
}
184+
}
99185
}

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: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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+
fill_switch(&switch_array[T2(0)], 0, 0, 0, 0, 0, 0, 0,
45+
vtr::strdup("short"), SwitchType::SHORT);
46+
fill_switch(&switch_array[T2(1)], 0, 0, 0, 0, 0, 0, 0,
47+
vtr::strdup("generic"), SwitchType::MUX);
48+
49+
const auto& pip_models = ar_.getPipTimings();
50+
float R, Cin, Cout, Cint, Tdel;
51+
std::string switch_name;
52+
SwitchType type;
53+
int id = 2;
54+
for (const auto& value : seen) {
55+
int timing_model_id;
56+
int mux_trans_size;
57+
bool buffered;
58+
std::tie(timing_model_id, buffered) = value;
59+
const auto& model = pip_models[timing_model_id];
60+
pips_models_.emplace_back(std::make_tuple(value, id));
61+
62+
R = Cin = Cint = Cout = Tdel = 0.0;
63+
std::stringstream name;
64+
std::string mux_type_string = buffered ? "mux_" : "passGate_";
65+
name << mux_type_string;
66+
67+
R = get_corner_value(model.getOutputResistance(), "slow", "min");
68+
name << "R" << std::scientific << R;
69+
70+
Cin = get_corner_value(model.getInputCapacitance(), "slow", "min");
71+
name << "Cin" << std::scientific << Cin;
72+
73+
Cout = get_corner_value(model.getOutputCapacitance(), "slow", "min");
74+
name << "Cout" << std::scientific << Cout;
75+
76+
if (buffered) {
77+
Cint = get_corner_value(model.getInternalCapacitance(), "slow", "min");
78+
name << "Cinternal" << std::scientific << Cint;
79+
}
80+
81+
Tdel = get_corner_value(model.getInternalDelay(), "slow", "min");
82+
name << "Tdel" << std::scientific << Tdel;
83+
84+
switch_name = name.str();
85+
type = buffered ? SwitchType::MUX : SwitchType::PASS_GATE;
86+
mux_trans_size = buffered ? 1 : 0;
87+
88+
fill_switch(&switch_array[T2(id)], R, Cin, Cout, Cint, Tdel,
89+
mux_trans_size, 0, vtr::strdup(switch_name.c_str()), type);
90+
91+
id++;
92+
}
93+
}

0 commit comments

Comments
 (0)