Skip to content

Commit 69e5725

Browse files
committed
RR_graph building for fpga interchange
Signed-off-by: Maciej Dudek <[email protected]>
1 parent fb9ad57 commit 69e5725

File tree

9 files changed

+1317
-106
lines changed

9 files changed

+1317
-106
lines changed

libs/EXTERNAL/libinterchange/interchange/DeviceResources.capnp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,8 @@ annotation wireRef(*) :WireRef;
5959
using WireIdx = UInt32;
6060

6161
struct WireTypeRef {
62-
type @0 :Ref.ReferenceType = parent;
62+
type @0 :Ref.ReferenceType = rootValue;
6363
field @1 :Text = "wireTypes";
64-
depth @2 :Int32 = 1;
6564
}
6665
annotation wireTypeRef(*) :WireTypeRef;
6766
using WireTypeIdx = UInt32;
@@ -81,19 +80,16 @@ using TileTypeSiteTypeIdx = UInt32;
8180
using TileTypeSubTileIdx = UInt16;
8281

8382
struct PIPTimingRef {
84-
type @0 :Ref.ReferenceType = parent;
85-
field @1 :Text = "pipTimingList";
86-
depth @2 :Int32 = 1;
83+
type @0 :Ref.ReferenceType = rootValue;
84+
field @1 :Text = "pipTimings";
8785

8886
}
8987
annotation pipTimingRef(*) :PIPTimingRef;
9088
using PipTimingIdx = UInt32;
9189

9290
struct NodeTimingRef {
93-
type @0 :Ref.ReferenceType = parent;
94-
field @1 :Text = "nodeTimingList";
95-
depth @2 :Int32 = 1;
96-
91+
type @0 :Ref.ReferenceType = rootValue;
92+
field @1 :Text = "nodeTimings";
9793
}
9894
annotation nodeTimingRef(*) :NodeTimingRef;
9995
using NodeTimingIdx = UInt32;
@@ -632,7 +628,7 @@ struct Device {
632628
}
633629

634630
struct PinDelay {
635-
pin @0 : BELPinIdx $belPinRef();
631+
pin @0 : BELPinIdx;
636632
union {
637633
noClock @1 : Void;
638634
clockEdge @2 : ClockEdge;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "fpga_interchange_arch_utils.h"
2+
3+
/****************** Utility functions ******************/
4+
5+
/**
6+
* @brief The FPGA interchange timing model includes three different corners (min, typ and max) for each of the two
7+
* speed_models (slow and fast).
8+
*
9+
* Timing data can be found on PIPs, nodes, site pins and bel pins.
10+
* This function retrieves the timing value based on the wanted speed model and the wanted corner.
11+
*
12+
* Corner model is considered valid if at least one configuration is set.
13+
* In that case this value shall be returned.
14+
*
15+
* More information on the FPGA Interchange timing model can be found here:
16+
* - https://github.com/chipsalliance/fpga-interchange-schema/blob/main/interchange/DeviceResources.capnp
17+
*/
18+
19+
float get_corner_value(DeviceResources::Device::CornerModel::Reader model, const char* speed_model, const char* value) {
20+
bool slow_model = std::string(speed_model) == std::string("slow");
21+
bool fast_model = std::string(speed_model) == std::string("fast");
22+
23+
bool min_corner = std::string(value) == std::string("min");
24+
bool typ_corner = std::string(value) == std::string("typ");
25+
bool max_corner = std::string(value) == std::string("max");
26+
27+
if (!slow_model && !fast_model) {
28+
archfpga_throw("", __LINE__, "Wrong speed model `%s`. Expected `slow` or `fast`\n", speed_model);
29+
}
30+
31+
if (!min_corner && !typ_corner && !max_corner) {
32+
archfpga_throw("", __LINE__, "Wrong corner model `%s`. Expected `min`, `typ` or `max`\n", value);
33+
}
34+
35+
bool has_fast = model.getFast().hasFast();
36+
bool has_slow = model.getSlow().hasSlow();
37+
38+
if ((slow_model || (fast_model && !has_fast)) && has_slow) {
39+
auto half = model.getSlow().getSlow();
40+
if (min_corner && half.getMin().isMin()) {
41+
return half.getMin().getMin();
42+
} else if (typ_corner && half.getTyp().isTyp()) {
43+
return half.getTyp().getTyp();
44+
} else if (max_corner && half.getMax().isMax()) {
45+
return half.getMax().getMax();
46+
} else {
47+
if (half.getMin().isMin()) {
48+
return half.getMin().getMin();
49+
} else if (half.getTyp().isTyp()) {
50+
return half.getTyp().getTyp();
51+
} else if (half.getMax().isMax()) {
52+
return half.getMax().getMax();
53+
} else {
54+
archfpga_throw("", __LINE__, "Invalid speed model %s. No value found!\n", speed_model);
55+
}
56+
}
57+
} else if ((fast_model || slow_model) && has_fast) {
58+
auto half = model.getFast().getFast();
59+
if (min_corner && half.getMin().isMin()) {
60+
return half.getMin().getMin();
61+
} else if (typ_corner && half.getTyp().isTyp()) {
62+
return half.getTyp().getTyp();
63+
} else if (max_corner && half.getMax().isMax()) {
64+
return half.getMax().getMax();
65+
} else {
66+
if (half.getMin().isMin()) {
67+
return half.getMin().getMin();
68+
} else if (half.getTyp().isTyp()) {
69+
return half.getTyp().getTyp();
70+
} else if (half.getMax().isMax()) {
71+
return half.getMax().getMax();
72+
} else {
73+
archfpga_throw("", __LINE__, "Invalid speed model %s. No value found!\n", speed_model);
74+
}
75+
}
76+
}
77+
return 0.;
78+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#ifndef FPGAINTERCHANGE_ARCH_UTILS_FILE_H
2+
#define FPGAINTERCHANGE_ARCH_UTILS_FILE_H
3+
4+
#include "arch_types.h"
5+
#include "arch_error.h"
6+
#include "vtr_error.h"
7+
8+
#include "DeviceResources.capnp.h"
9+
#include "LogicalNetlist.capnp.h"
10+
#include "capnp/serialize.h"
11+
#include "capnp/serialize-packed.h"
12+
#include <fcntl.h>
13+
#include <unistd.h>
14+
15+
#ifdef __cplusplus
16+
extern "C" {
17+
#endif
18+
19+
/****************** Utility functions ******************/
20+
21+
/**
22+
* @brief The FPGA interchange timing model includes three different corners (min, typ and max) for each of the two
23+
* speed_models (slow and fast).
24+
*
25+
* Timing data can be found on PIPs, nodes, site pins and bel pins.
26+
* This function retrieves the timing value based on the wanted speed model and the wanted corner.
27+
*
28+
* Corner model is considered valid if at least one configuration is set.
29+
* In that case this value shall be returned.
30+
*
31+
* More information on the FPGA Interchange timing model can be found here:
32+
* - https://github.com/chipsalliance/fpga-interchange-schema/blob/main/interchange/DeviceResources.capnp
33+
*/
34+
35+
float get_corner_value(DeviceResources::Device::CornerModel::Reader model, const char* speed_model, const char* value);
36+
37+
#ifdef __cplusplus
38+
}
39+
#endif
40+
41+
#endif

libs/libarchfpga/src/read_fpga_interchange_arch.cpp

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "arch_types.h"
2222

2323
#include "read_fpga_interchange_arch.h"
24+
#include "fpga_interchange_arch_utils.h"
2425

2526
/*
2627
* FPGA Interchange Device frontend
@@ -78,82 +79,6 @@ struct t_ic_data {
7879

7980
/****************** Utility functions ******************/
8081

81-
/**
82-
* @brief The FPGA interchange timing model includes three different corners (min, typ and max) for each of the two
83-
* speed_models (slow and fast).
84-
*
85-
* Timing data can be found on PIPs, nodes, site pins and bel pins.
86-
* This function retrieves the timing value based on the wanted speed model and the wanted corner.
87-
*
88-
* More information on the FPGA Interchange timing model can be found here:
89-
* - https://github.com/chipsalliance/fpga-interchange-schema/blob/main/interchange/DeviceResources.capnp
90-
*/
91-
static float get_corner_value(Device::CornerModel::Reader model, const char* speed_model, const char* value) {
92-
bool slow_model = std::string(speed_model) == std::string("slow");
93-
bool fast_model = std::string(speed_model) == std::string("fast");
94-
95-
bool min_corner = std::string(value) == std::string("min");
96-
bool typ_corner = std::string(value) == std::string("typ");
97-
bool max_corner = std::string(value) == std::string("max");
98-
99-
if (!slow_model && !fast_model) {
100-
archfpga_throw("", __LINE__,
101-
"Wrong speed model `%s`. Expected `slow` or `fast`\n", speed_model);
102-
}
103-
104-
if (!min_corner && !typ_corner && !max_corner) {
105-
archfpga_throw("", __LINE__,
106-
"Wrong corner model `%s`. Expected `min`, `typ` or `max`\n", value);
107-
}
108-
109-
bool has_fast = model.getFast().hasFast();
110-
bool has_slow = model.getSlow().hasSlow();
111-
112-
if (slow_model && has_slow) {
113-
auto half = model.getSlow().getSlow();
114-
if (min_corner && half.getMin().isMin()) {
115-
return half.getMin().getMin();
116-
} else if (typ_corner && half.getTyp().isTyp()) {
117-
return half.getTyp().getTyp();
118-
} else if (max_corner && half.getMax().isMax()) {
119-
return half.getMax().getMax();
120-
} else {
121-
if (half.getMin().isMin()) {
122-
return half.getMin().getMin();
123-
} else if (half.getTyp().isTyp()) {
124-
return half.getTyp().getTyp();
125-
} else if (half.getMax().isMax()) {
126-
return half.getMax().getMax();
127-
} else {
128-
archfpga_throw("", __LINE__,
129-
"Invalid speed model %s. No value found!\n", speed_model);
130-
}
131-
}
132-
} else if (fast_model && has_fast) {
133-
auto half = model.getFast().getFast();
134-
if (min_corner && half.getMin().isMin()) {
135-
return half.getMin().getMin();
136-
} else if (typ_corner && half.getTyp().isTyp()) {
137-
return half.getTyp().getTyp();
138-
} else if (max_corner && half.getMax().isMax()) {
139-
return half.getMax().getMax();
140-
} else {
141-
if (half.getMin().isMin()) {
142-
return half.getMin().getMin();
143-
} else if (half.getTyp().isTyp()) {
144-
return half.getTyp().getTyp();
145-
} else if (half.getMax().isMax()) {
146-
return half.getMax().getMax();
147-
} else {
148-
archfpga_throw("", __LINE__,
149-
"Invalid speed model %s. No value found!\n", speed_model);
150-
}
151-
}
152-
}
153-
154-
return 0.;
155-
}
156-
15782
/** @brief Returns the port corresponding to the given model in the architecture */
15883
static t_model_ports* get_model_port(t_arch* arch, std::string model, std::string port, bool fail = true) {
15984
for (t_model* m : {arch->models, arch->model_library}) {
@@ -2414,17 +2339,11 @@ struct ArchReader {
24142339
}
24152340
}
24162341

2417-
// FIXME: have only one segment type for the time being, so that
2418-
// the RR graph generation is correct.
2419-
// This can be removed once the RR graph reader from the interchange
2420-
// device is ready and functional.
2421-
size_t num_seg = 1; //wire_names.size();
2342+
int num_seg = wire_names.size();
24222343

24232344
arch_->Segments.resize(num_seg);
24242345
size_t index = 0;
24252346
for (auto i : wire_names) {
2426-
if (index >= num_seg) break;
2427-
24282347
// Use default values as we will populate rr_graph with correct values
24292348
// This segments are just declaration of future use
24302349
arch_->Segments[index].name = str(i);

vpr/src/base/SetupVPR.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts)
421421

422422
RouterOpts->max_logged_overused_rr_nodes = Options.max_logged_overused_rr_nodes;
423423
RouterOpts->generate_rr_node_overuse_report = Options.generate_rr_node_overuse_report;
424-
RouterOpts->FPGAInterchange = Options.FPGAInterchangeDevice;
424+
RouterOpts->FPGAInterchange = (Options.arch_format == e_arch_format::FPGAInterchange);
425425
}
426426

427427
static void SetupAnnealSched(const t_options& Options,

vpr/src/base/vpr_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,9 @@ struct t_router_opts {
12781278
e_rr_node_reorder_algorithm reorder_rr_graph_nodes_algorithm = DONT_REORDER;
12791279
int reorder_rr_graph_nodes_threshold = 0;
12801280
int reorder_rr_graph_nodes_seed = 1;
1281+
1282+
// Options related to FPGA Interchange
1283+
bool FPGAInterchange;
12811284
};
12821285

12831286
struct t_analysis_opts {

vpr/src/route/rr_graph.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ void create_rr_graph(const t_graph_type graph_type,
318318
auto& mutable_device_ctx = g_vpr_ctx.mutable_device();
319319

320320
if (!det_routing_arch->read_rr_graph_filename.empty() || router_opts.FPGAInterchange) {
321-
if (device_ctx.read_rr_graph_filename != det_routing_arch->read_rr_graph_filename) {
321+
if (device_ctx.read_rr_graph_filename != det_routing_arch->read_rr_graph_filename && !router_opts.FPGAInterchange) {
322322
free_rr_graph();
323323

324324
load_rr_file(graph_type,
@@ -343,11 +343,7 @@ void create_rr_graph(const t_graph_type graph_type,
343343
segment_inf,
344344
router_opts.base_cost_type,
345345
&det_routing_arch->wire_to_rr_ipin_switch,
346-
det_routing_arch->read_rr_graph_filename.c_str(),
347-
router_opts.read_rr_edge_metadata,
348346
router_opts.do_check_rr_graph);
349-
350-
exit(0);
351347
if (router_opts.reorder_rr_graph_nodes_algorithm != DONT_REORDER) {
352348
mutable_device_ctx.rr_graph_builder.reorder_nodes(router_opts.reorder_rr_graph_nodes_algorithm,
353349
router_opts.reorder_rr_graph_nodes_threshold,

0 commit comments

Comments
 (0)