blob: 28ab1c79d7f97932149d290917b63140fe77935b [file] [log] [blame]
// Core of the FPGA assembly (FASM) output code.
//
// The netlist walker implements the core walking of the netlist and routing
// graph with the intention of emitting the complete implemented design to the
// output FASM file. Once output, the FASM file is expected to completely
// describe the features required to implement the design in a hardware
// bitstream.
#ifndef FASM_H
#define FASM_H
#include <iostream>
#include <list>
#include <map>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#include "netlist_walker.h"
#include "netlist_writer.h"
#include "lut.h"
#include "parameters.h"
#include "route_tree_type.h"
namespace fasm {
// FASM netlist visitor.
//
// This netlist visitor emits FASM features to the provided ostream using
// FASM metadata tags. See the FASM documentation in docs/utils/fasm.rst
// for a complete list of tags.
//
// High level methodology:
// - At each top level pb_type, root tile FASM prefix is checked.
// - At each pb_type, the CLB prefix is build by walking from the child to
// the root pb_type.
// - All LUTs are visited and emitted via the fasm_type/fasm_lut tags.
// - All route through wires are emitted via the same mechanism as LUTs.
// - All atom's (e.g. leaf pb_types) are visited and have their parameters
// emitted via fasm_params tags.
// - All pb_type interconnect's are visited and are emitted via fasm_mux tags.
// - All pb_type and pb_type mode's are checked for static feature emission
// via the fasm_features tag.
//
// Once the netlist visitor is done, in finish_impl, the routing graph is
// walked and static features are emitted via the fasm_features tag.
//
// Note that FASM features are incrementally written the ostream as they are
// seen, so the order of FASM output is arbitrary based on the walk order of
// the netlist and routing graph.
class FasmWriterVisitor : public NetlistVisitor {
public:
FasmWriterVisitor(std::ostream& f);
private:
void visit_top_impl(const char* top_level_name) override;
void visit_route_through_impl(const t_pb* atom) override;
void visit_atom_impl(const t_pb* atom) override;
// clb in visit_clb_impl stands for complex logic block.
// visit_clb_impl is called on each top-level pb_type used in the design.
void visit_clb_impl(ClusterBlockId blk_id, const t_pb* clb) override;
void visit_all_impl(const t_pb_routes &top_pb_route, const t_pb* pb) override;
void finish_impl() override;
private:
void output_fasm_features(const std::string features) const;
void output_fasm_features(const std::string features, const std::string clb_prefix, const std::string blk_prefix) const;
void check_features(const t_metadata_dict *meta) const;
void check_interconnect(const t_pb_routes &pb_route, int inode);
void check_for_lut(const t_pb* atom);
void output_fasm_mux(std::string fasm_mux, t_interconnect *interconnect, t_pb_graph_pin *mux_input_pin);
void walk_routing();
void walk_route_tree(const t_rt_node *root);
std::string build_clb_prefix(const t_pb *pb, const t_pb_graph_node* pb_graph_node, bool* is_parent_pb_null) const;
const LutOutputDefinition* find_lut(const t_pb_graph_node* pb_graph_node);
void check_for_param(const t_pb *atom);
// Walk from node to parents and search for a CLB prefix.
void find_clb_prefix(const t_pb_graph_node *node,
bool *have_prefix, std::string *clb_prefix) const;
std::ostream& os_;
t_pb_graph_node *root_clb_;
bool current_blk_has_prefix_;
t_physical_tile_type_ptr blk_type_;
std::string blk_prefix_;
std::string clb_prefix_;
std::map<const t_pb_graph_node *, std::string> clb_prefix_map_;
ClusterBlockId current_blk_id_;
std::vector<t_pb_graph_pin**> pb_graph_pin_lookup_from_index_by_type_;
std::map<const t_pb_type*, std::vector<std::pair<std::string, LutOutputDefinition>>> lut_definitions_;
std::map<const t_pb_type*, Parameters> parameters_;
std::map<const std::string, std::string> tags_;
};
} // namespace fasm
#endif // FASM_H