| // Tool to output FASM from placed and routed design via metadata tagging. | |
| #include <cstdio> | |
| #include <cstring> | |
| #include <ctime> | |
| #include <fstream> | |
| using namespace std; | |
| #include "vtr_error.h" | |
| #include "vtr_memory.h" | |
| #include "vtr_log.h" | |
| #include "tatum/error.hpp" | |
| #include "vpr_error.h" | |
| #include "vpr_api.h" | |
| #include "vpr_signal_handler.h" | |
| #include "globals.h" | |
| #include "net_delay.h" | |
| #include "RoutingDelayCalculator.h" | |
| #include "fasm.h" | |
| /* | |
| * Exit codes to signal success/failure to scripts | |
| * calling vpr | |
| */ | |
| constexpr int SUCCESS_EXIT_CODE = 0; //Everything OK | |
| constexpr int ERROR_EXIT_CODE = 1; //Something went wrong internally | |
| constexpr int UNIMPLEMENTABLE_EXIT_CODE = 2; //Could not implement (e.g. unroutable) | |
| constexpr int INTERRUPTED_EXIT_CODE = 3; //VPR was interrupted by the user (e.g. SIGINT/ctr-C) | |
| /* | |
| * Writes FASM file based on the netlist name by walking the netlist. | |
| */ | |
| static bool write_fasm() { | |
| auto& atom_ctx = g_vpr_ctx.atom(); | |
| std::string fasm_filename = atom_ctx.nlist.netlist_name() + ".fasm"; | |
| vtr::printf("Writing Implementation FASM: %s\n", fasm_filename.c_str()); | |
| std::ofstream fasm_os(fasm_filename); | |
| fasm::FasmWriterVisitor visitor(fasm_os); | |
| NetlistWalker nl_walker(visitor); | |
| nl_walker.walk(); | |
| return true; | |
| } | |
| /* | |
| * Generate FASM utility. | |
| * | |
| * 1. Loads pack, place and route files | |
| * 2. Walks netlist and outputs FASM. | |
| * 3. Cleans up and exits. | |
| * | |
| */ | |
| int main(int argc, const char **argv) { | |
| t_options Options = t_options(); | |
| t_arch Arch = t_arch(); | |
| t_vpr_setup vpr_setup = t_vpr_setup(); | |
| clock_t entire_flow_begin, entire_flow_end; | |
| entire_flow_begin = clock(); | |
| try { | |
| vpr_install_signal_handler(); | |
| /* Read options, architecture, and circuit netlist */ | |
| vpr_init(argc, 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 = false; | |
| flow_succeeded = vpr_flow(vpr_setup, Arch); | |
| /* Actually write output FASM file. */ | |
| flow_succeeded = write_fasm(); | |
| if (!flow_succeeded) { | |
| return UNIMPLEMENTABLE_EXIT_CODE; | |
| } | |
| entire_flow_end = clock(); | |
| vtr::printf_info("The entire flow of VPR took %g seconds.\n", | |
| (float) (entire_flow_end - entire_flow_begin) / CLOCKS_PER_SEC); | |
| /* free data structures */ | |
| vpr_free_all(Arch, vpr_setup); | |
| } catch (const tatum::Error& tatum_error) { | |
| vtr::printf_error(__FILE__, __LINE__, "STA Engine: %s\n", tatum_error.what()); | |
| return ERROR_EXIT_CODE; | |
| } catch (const VprError& vpr_error) { | |
| vpr_print_error(vpr_error); | |
| if (vpr_error.type() == VPR_ERROR_INTERRUPTED) { | |
| return INTERRUPTED_EXIT_CODE; | |
| } else { | |
| return ERROR_EXIT_CODE; | |
| } | |
| } catch (const vtr::VtrError& vtr_error) { | |
| vtr::printf_error(__FILE__, __LINE__, "%s:%d %s\n", vtr_error.filename_c_str(), vtr_error.line(), vtr_error.what()); | |
| return ERROR_EXIT_CODE; | |
| } | |
| /* Signal success to scripts */ | |
| return SUCCESS_EXIT_CODE; | |
| } |