blob: 36fbe09e4e80149e2fb23ef24895de7665bd6e89 [file] [log] [blame]
#include "catch.hpp"
#include "vpr_api.h"
#include "vtr_util.h"
#include "rr_metadata.h"
#include "fasm.h"
#include "arch_util.h"
#include "rr_graph_writer.h"
#include <sstream>
#include <fstream>
static constexpr const char kArchFile[] = "test_fasm_arch.xml";
static constexpr const char kRrGraphFile[] = "test_fasm_rrgraph.xml";
namespace {
using Catch::Matchers::Equals;
TEST_CASE("fasm_integration_test", "[fasm]") {
{
t_vpr_setup vpr_setup;
t_arch arch;
t_options options;
const char *argv[] = {
"test_vpr",
kArchFile,
"wire.eblif",
"--route_chan_width",
"100",
};
vpr_init(sizeof(argv)/sizeof(argv[0]), argv,
&options, &vpr_setup, &arch);
bool flow_succeeded = vpr_flow(vpr_setup, arch);
REQUIRE(flow_succeeded == true);
auto &device_ctx = g_vpr_ctx.mutable_device();
for(size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
for(t_edge_size iedge = 0; iedge < device_ctx.rr_nodes[inode].num_edges(); ++iedge) {
auto sink_inode = device_ctx.rr_nodes[inode].edge_sink_node(iedge);
auto switch_id = device_ctx.rr_nodes[inode].edge_switch(iedge);
vpr::add_rr_edge_metadata(inode, sink_inode, switch_id,
"fasm_features", vtr::string_fmt("%d_%d_%zu",
inode, sink_inode, switch_id));
}
}
write_rr_graph(kRrGraphFile, vpr_setup.Segments);
vpr_free_all(arch, vpr_setup);
}
t_vpr_setup vpr_setup;
t_arch arch;
t_options options;
const char *argv[] = {
"test_vpr",
kArchFile,
"wire.eblif",
"--route_chan_width",
"100",
"--read_rr_graph",
kRrGraphFile,
};
vpr_init(sizeof(argv)/sizeof(argv[0]), argv,
&options, &vpr_setup, &arch);
vpr_setup.PackerOpts.doPacking = STAGE_LOAD;
vpr_setup.PlacerOpts.doPlacement = STAGE_LOAD;
vpr_setup.RouterOpts.doRouting = STAGE_LOAD;
vpr_setup.AnalysisOpts.doAnalysis = STAGE_SKIP;
bool flow_succeeded = vpr_flow(vpr_setup, arch);
REQUIRE(flow_succeeded == true);
std::stringstream fasm_string;
fasm::FasmWriterVisitor visitor(fasm_string);
NetlistWalker nl_walker(visitor);
nl_walker.walk();
fasm_string.seekg(0);
std::ofstream fasm_file("output.fasm", std::ios_base::out);
while(fasm_string) {
std::string line;
std::getline(fasm_string, line);
fasm_file << line << std::endl;
}
fasm_string.clear();
fasm_string.seekg(0);
std::set<std::tuple<int, int, short>> routing_edges;
bool found_lut5 = false;
bool found_lut6 = false;
bool found_mux1 = false;
bool found_mux2 = false;
bool found_mux3 = false;
while(fasm_string) {
// Should see something like:
// CLB.FLE0.N2_LUT5
// CLB.FLE8.LUT5_1.LUT[31:0]=32'b00000000000000010000000000000000
// CLB.FLE9.OUT_MUX.LUT
// CLB.FLE9.DISABLE_FF
// CLB.FLE9.LUT6[63:0]=64'b0000000000000000000000000000000100000000000000000000000000000000
// 3634_3690_0
std::string line;
std::getline(fasm_string, line);
if(line == "") {
continue;
}
if(!found_mux1 && line.find(".OUT_MUX.LUT") != std::string::npos) {
found_mux1 = true;
}
if(!found_mux2 && line.find(".DISABLE_FF") != std::string::npos) {
found_mux2 = true;
}
if(!found_mux3 && line.find(".IN0") != std::string::npos) {
found_mux3 = true;
}
if(line.find("CLB") != std::string::npos || line.find("FLE") != std::string::npos) {
auto pos = line.find("LUT[");
if(pos != std::string::npos) {
CHECK_THAT(line.substr(pos), Equals(
"LUT[31:0]=32'b00000000000000010000000000000000"));
found_lut5 = true;
}
pos = line.find("LUT6[");
if(pos != std::string::npos) {
CHECK_THAT(line.substr(pos), Equals("LUT6[63:0]=64'b0000000000000000000000000000000100000000000000000000000000000000"));
found_lut6 = true;
}
} else {
auto parts = vtr::split(line, "_");
REQUIRE(parts.size() == 3);
auto src_inode = vtr::atoi(parts[0]);
auto sink_inode = vtr::atoi(parts[1]);
auto switch_id = vtr::atoi(parts[2]);
auto ret = routing_edges.insert(std::make_tuple(src_inode, sink_inode, switch_id));
CHECK(ret.second == true);
}
}
const auto & route_ctx = g_vpr_ctx.routing();
for(const auto &trace : route_ctx.trace) {
const t_trace *head = trace.head;
while(head != nullptr) {
const t_trace *next = head->next;
if(next != nullptr) {
const auto next_inode = next->index;
auto iter = routing_edges.find(std::make_tuple(head->index, next_inode, head->iswitch));
CHECK(iter != routing_edges.end());
}
head = next;
}
}
CHECK(found_lut5);
CHECK(found_lut6);
CHECK(found_mux1);
CHECK(found_mux2);
CHECK(found_mux3);
vpr_free_all(arch, vpr_setup);
}
} // namespace