develop and plug mux_lib_builder, refactoring the mux submodule generation
This commit is contained in:
parent
27b619554d
commit
63f40f48fa
|
@ -43,6 +43,16 @@ CircuitModelId MuxLibrary::mux_circuit_model(const MuxId& mux_id) const {
|
|||
return mux_circuit_models_[mux_id];
|
||||
}
|
||||
|
||||
/* Find the maximum mux size among the mux graphs */
|
||||
size_t MuxLibrary::max_mux_size() const {
|
||||
/* Iterate over all the mux graphs and find their sizes */
|
||||
size_t max_mux_size = 0;
|
||||
for (const auto& mux : mux_ids_) {
|
||||
max_mux_size = std::max(max_mux_size, mux_graphs_[mux].num_inputs());
|
||||
}
|
||||
return max_mux_size;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Private mutators:
|
||||
*************************************************/
|
||||
|
|
|
@ -27,6 +27,8 @@ class MuxLibrary {
|
|||
const MuxGraph& mux_graph(const MuxId& mux_id) const;
|
||||
/* Get a mux circuit model id */
|
||||
CircuitModelId mux_circuit_model(const MuxId& mux_id) const;
|
||||
/* Find the maximum mux size */
|
||||
size_t max_mux_size() const;
|
||||
public: /* Public mutators */
|
||||
/* Add a mux to the library */
|
||||
void add_mux(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size);
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
/********************************************************************
|
||||
* This file includes the functions of builders for MuxLibrary.
|
||||
*******************************************************************/
|
||||
#include <cmath>
|
||||
#include <stdio.h>
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* Device-level header files */
|
||||
#include "util.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
|
||||
/* FPGA-X2P context header files */
|
||||
#include "fpga_x2p_utils.h"
|
||||
|
||||
#include "spice_types.h"
|
||||
#include "circuit_library.h"
|
||||
#include "mux_library.h"
|
||||
#include "mux_library_builder.h"
|
||||
|
||||
/********************************************************************
|
||||
* Update MuxLibrary with the unique multiplexer structures
|
||||
* found in the global routing architecture
|
||||
*******************************************************************/
|
||||
static
|
||||
void build_routing_arch_mux_library(MuxLibrary& mux_lib,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_switch_inf* switches,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
t_det_routing_arch* routing_arch) {
|
||||
/* Current Version: Support Uni-directional routing architecture only*/
|
||||
if (UNI_DIRECTIONAL != routing_arch->directionality) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(FILE:%s, LINE[%d]) FPGA X2P Only supports uni-directional routing architecture.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The routing path is.
|
||||
* OPIN ----> CHAN ----> ... ----> CHAN ----> IPIN
|
||||
* Each edge is a switch, for IPIN, the switch is a connection block,
|
||||
* for the rest is a switch box
|
||||
*/
|
||||
/* Count the sizes of muliplexers in routing architecture */
|
||||
for (int inode = 0; inode < LL_num_rr_nodes; inode++) {
|
||||
t_rr_node& node = LL_rr_node[inode];
|
||||
switch (node.type) {
|
||||
case IPIN: {
|
||||
/* Have to consider the fan_in only, it is a connection block (multiplexer)*/
|
||||
VTR_ASSERT((node.fan_in > 0) || (0 == node.fan_in));
|
||||
if ( (0 == node.fan_in) || (1 == node.fan_in)) {
|
||||
break;
|
||||
}
|
||||
/* Find the circuit_model for multiplexers in connection blocks */
|
||||
const CircuitModelId& cb_switch_circuit_model = switches[node.driver_switch].circuit_model;
|
||||
/* we should select a circuit model for the connection box*/
|
||||
VTR_ASSERT(CircuitModelId::INVALID() != cb_switch_circuit_model);
|
||||
/* Add the mux to mux_library */
|
||||
mux_lib.add_mux(circuit_lib, cb_switch_circuit_model, node.fan_in);
|
||||
break;
|
||||
}
|
||||
case CHANX:
|
||||
case CHANY: {
|
||||
/* Channels are the same, have to consider the fan_in as well,
|
||||
* it could be a switch box if previous rr_node is a channel
|
||||
* or it could be a connection box if previous rr_node is a IPIN or OPIN
|
||||
*/
|
||||
VTR_ASSERT((node.fan_in > 0) || (0 == node.fan_in));
|
||||
if ((0 == node.fan_in) || (1 == node.fan_in)) {
|
||||
break;
|
||||
}
|
||||
/* Find the spice_model for multiplexers in switch blocks*/
|
||||
const CircuitModelId& sb_switch_circuit_model = switches[node.driver_switch].circuit_model;
|
||||
/* we should select a circuit model for the Switch box*/
|
||||
VTR_ASSERT(CircuitModelId::INVALID() != sb_switch_circuit_model);
|
||||
/* Add the mux to mux_library */
|
||||
mux_lib.add_mux(circuit_lib, sb_switch_circuit_model, node.fan_in);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* We do not care other types of rr_node */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Update MuxLibrary with the unique multiplexer structures
|
||||
* found in programmable logic blocks
|
||||
********************************************************************/
|
||||
static
|
||||
void build_pb_type_mux_library_rec(MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
t_pb_type* cur_pb_type) {
|
||||
VTR_ASSERT(nullptr != cur_pb_type);
|
||||
|
||||
/* If there is spice_model_name, this is a leaf node!*/
|
||||
if (TRUE == is_primitive_pb_type(cur_pb_type)) {
|
||||
/* What annoys me is VPR create a sub pb_type for each lut which suppose to be a leaf node
|
||||
* This may bring software convience but ruins circuit modeling
|
||||
*/
|
||||
VTR_ASSERT(CircuitModelId::INVALID() != cur_pb_type->phy_pb_type->circuit_model);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Traversal the hierarchy, find all the multiplexer from the interconnection part */
|
||||
for (int imode = 0; imode < cur_pb_type->num_modes; imode++) {
|
||||
/* Then we have to statisitic the interconnections*/
|
||||
for (int jinterc = 0; jinterc < cur_pb_type->modes[imode].num_interconnect; jinterc++) {
|
||||
/* Check the num_mux and fan_in of an interconnection */
|
||||
VTR_ASSERT ((0 == cur_pb_type->modes[imode].interconnect[jinterc].num_mux)
|
||||
|| (0 < cur_pb_type->modes[imode].interconnect[jinterc].num_mux));
|
||||
if (0 == cur_pb_type->modes[imode].interconnect[jinterc].num_mux) {
|
||||
continue;
|
||||
}
|
||||
CircuitModelId& interc_circuit_model = cur_pb_type->modes[imode].interconnect[jinterc].circuit_model;
|
||||
VTR_ASSERT(CircuitModelId::INVALID() != interc_circuit_model);
|
||||
/* Add the mux model to library */
|
||||
mux_lib.add_mux(circuit_lib, interc_circuit_model, cur_pb_type->modes[imode].interconnect[jinterc].fan_in);
|
||||
}
|
||||
}
|
||||
|
||||
/* Go recursively to the lower level */
|
||||
for (int imode = 0; imode < cur_pb_type->num_modes; imode++) {
|
||||
for (int ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ichild++) {
|
||||
build_pb_type_mux_library_rec(mux_lib, circuit_lib,
|
||||
&cur_pb_type->modes[imode].pb_type_children[ichild]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Update MuxLibrary with the unique multiplexers required by
|
||||
* LUTs in the circuit library
|
||||
********************************************************************/
|
||||
static
|
||||
void build_lut_mux_library(MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib) {
|
||||
/* Find all the circuit models which are LUTs in the circuit library */
|
||||
for (const auto& circuit_model : circuit_lib.models()) {
|
||||
/* Bypass non-LUT circuit models */
|
||||
if (SPICE_MODEL_LUT != circuit_lib.model_type(circuit_model)) {
|
||||
continue;
|
||||
}
|
||||
/* Find the MUX size required by the LUT */
|
||||
/* Get input ports which are not global ports! */
|
||||
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
VTR_ASSERT(1 == input_ports.size());
|
||||
/* MUX size = 2^lut_size */
|
||||
size_t lut_mux_size = (size_t)pow(2., (double)(circuit_lib.port_size(input_ports[0])));
|
||||
/* Add mux to the mux library */
|
||||
mux_lib.add_mux(circuit_lib, circuit_model, lut_mux_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Statistic for all the multiplexers in FPGA
|
||||
* We determine the sizes and its structure (according to spice_model) for each type of multiplexers
|
||||
* We search multiplexers in Switch Blocks, Connection blocks and Configurable Logic Blocks
|
||||
* In additional to multiplexers, this function also consider crossbars.
|
||||
* All the statistics are stored in a linked list, as a return value
|
||||
*/
|
||||
MuxLibrary build_device_mux_library(int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_switch_inf* switches,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
t_det_routing_arch* routing_arch) {
|
||||
/* MuxLibrary to store the information of Multiplexers*/
|
||||
MuxLibrary mux_lib;
|
||||
|
||||
/* Step 1: We should check the multiplexer spice models defined in routing architecture.*/
|
||||
build_routing_arch_mux_library(mux_lib, LL_num_rr_nodes, LL_rr_node, switches, circuit_lib, routing_arch);
|
||||
|
||||
/* Step 2: Count the sizes of multiplexers in complex logic blocks */
|
||||
for (int itype = 0; itype < num_types; itype++) {
|
||||
if (NULL != type_descriptors[itype].pb_type) {
|
||||
build_pb_type_mux_library_rec(mux_lib, circuit_lib, type_descriptors[itype].pb_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 3: count the size of multiplexer that will be used in LUTs*/
|
||||
build_lut_mux_library(mux_lib, circuit_lib);
|
||||
|
||||
return mux_lib;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/********************************************************************
|
||||
* This file includes the function declaration of builders
|
||||
* for MuxLibrary.
|
||||
* See details in mux_library_builder.cpp
|
||||
*******************************************************************/
|
||||
#ifndef MUX_LIBRARY_BUILDER_H
|
||||
#define MUX_LIBRARY_BUILDER_H
|
||||
|
||||
MuxLibrary build_device_mux_library(int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_switch_inf* switches,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
t_det_routing_arch* routing_arch);
|
||||
|
||||
#endif
|
|
@ -29,6 +29,7 @@ std::string generate_verilog_mux_subckt_name(const CircuitLibrary& circuit_lib,
|
|||
std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const size_t& mux_size,
|
||||
const size_t& branch_mux_size,
|
||||
const std::string& postfix) {
|
||||
/* If the tgate spice model of this MUX is a MUX2 standard cell,
|
||||
* the mux_subckt name will be the name of the standard cell
|
||||
|
@ -38,6 +39,7 @@ std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circui
|
|||
VTR_ASSERT (SPICE_MODEL_GATE_MUX2 == circuit_lib.gate_type(subckt_model));
|
||||
return circuit_lib.model_name(subckt_model);
|
||||
}
|
||||
std::string branch_postfix = postfix + "_size" + std::to_string(branch_mux_size);
|
||||
|
||||
return generate_verilog_mux_subckt_name(circuit_lib, circuit_model, mux_size, postfix);
|
||||
return generate_verilog_mux_subckt_name(circuit_lib, circuit_model, mux_size, branch_postfix);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ std::string generate_verilog_mux_subckt_name(const CircuitLibrary& circuit_lib,
|
|||
std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const size_t& mux_size,
|
||||
const size_t& branch_mux_size,
|
||||
const std::string& posfix);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include "fpga_bitstream.h"
|
||||
|
||||
#include "module_manager.h"
|
||||
#include "mux_library.h"
|
||||
#include "mux_library_builder.h"
|
||||
|
||||
/* Include SynVerilog headers */
|
||||
#include "verilog_global.h"
|
||||
|
@ -153,6 +155,11 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
|
|||
/* Module manager for the Verilog modules created */
|
||||
ModuleManager module_manager;
|
||||
|
||||
/* Build Multiplexer library */
|
||||
MuxLibrary mux_lib = build_device_mux_library(num_rr_nodes, rr_node, switch_inf, Arch.spice->circuit_lib, &vpr_setup.RoutingArch);
|
||||
|
||||
/* 0. basic units: inverter, buffers and pass-gate logics, */
|
||||
|
||||
/* Check if the routing architecture we support*/
|
||||
if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "FPGA synthesizable Verilog dumping only support uni-directional routing architecture!\n");
|
||||
|
@ -274,7 +281,7 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
|
|||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
|
||||
|
||||
/* Dump internal structures of submodules */
|
||||
dump_verilog_submodules(module_manager, sram_verilog_orgz_info, src_dir_path, submodule_dir_path,
|
||||
dump_verilog_submodules(module_manager, mux_lib, sram_verilog_orgz_info, src_dir_path, submodule_dir_path,
|
||||
Arch, &vpr_setup.RoutingArch,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
|
||||
|
||||
|
|
|
@ -507,7 +507,7 @@ void print_verilog_submodule_essentials(ModuleManager& module_manager,
|
|||
/* Create file */
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Generating Verilog netlist (%s) for essential gates...\n",
|
||||
__FILE__, __LINE__, essentials_verilog_file_name);
|
||||
__FILE__, __LINE__, verilog_fname.c_str());
|
||||
|
||||
print_verilog_file_header(fp, "Essential gates");
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
/* Device-level header files */
|
||||
#include "mux_graph.h"
|
||||
#include "module_manager.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
|
||||
|
@ -30,8 +31,9 @@
|
|||
* for a multiplexer with the given size
|
||||
**********************************************/
|
||||
static
|
||||
void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp,
|
||||
void generate_verilog_cmos_mux_branch_module_structural(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
std::fstream& fp,
|
||||
const CircuitModelId& circuit_model,
|
||||
const std::string& module_name,
|
||||
const MuxGraph& mux_graph) {
|
||||
|
@ -44,7 +46,7 @@ void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Get model ports of tgate */
|
||||
/* TODO: move to check_circuit_library? Get model ports of tgate */
|
||||
std::vector<CircuitPortId> tgate_input_ports = circuit_lib.model_ports_by_type(tgate_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
std::vector<CircuitPortId> tgate_output_ports = circuit_lib.model_ports_by_type(tgate_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||
std::vector<CircuitPortId> tgate_global_ports = circuit_lib.model_global_ports_by_type(tgate_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
|
@ -68,36 +70,30 @@ void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp,
|
|||
/* MUX graph must have only 1 level*/
|
||||
VTR_ASSERT(1 == mux_graph.num_levels());
|
||||
|
||||
/* Print Verilog module */
|
||||
print_verilog_module_definition(fp, module_name);
|
||||
|
||||
/* Create port information */
|
||||
/* Configure each input port */
|
||||
BasicPort input_port("in", num_inputs);
|
||||
|
||||
/* Configure each output port */
|
||||
BasicPort output_port("out", num_outputs);
|
||||
|
||||
/* Configure each memory port */
|
||||
BasicPort mem_port("mem", num_mems);
|
||||
BasicPort mem_inv_port("mem_inv", num_mems);
|
||||
|
||||
/* TODO: Generate global ports */
|
||||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId module_id = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(ModuleId::INVALID() != module_id);
|
||||
/* Add module ports */
|
||||
/* Add each global port */
|
||||
for (const auto& port : tgate_global_ports) {
|
||||
/* Configure each global port */
|
||||
BasicPort basic_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
/* Print port */
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl;
|
||||
BasicPort global_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||
module_manager.add_port(module_id, global_port, ModuleManager::MODULE_GLOBAL_PORT);
|
||||
}
|
||||
/* Add each input port */
|
||||
BasicPort input_port("in", num_inputs);
|
||||
module_manager.add_port(module_id, input_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
/* Add each output port */
|
||||
BasicPort output_port("out", num_outputs);
|
||||
module_manager.add_port(module_id, output_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
/* Add each memory port */
|
||||
BasicPort mem_port("mem", num_mems);
|
||||
module_manager.add_port(module_id, mem_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
BasicPort mem_inv_port("mem_inv", num_mems);
|
||||
module_manager.add_port(module_id, mem_inv_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
|
||||
/* TODO: add a module to the Module Manager */
|
||||
|
||||
/* Port list */
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, input_port) << "," << std::endl;
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_OUTPUT, output_port) << "," << std::endl;
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, mem_port) << "," << std::endl;
|
||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, mem_inv_port) << std::endl;
|
||||
fp << ");" << std::endl;
|
||||
/* dump module definition + ports */
|
||||
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||
|
||||
/* Verilog Behavior description for a MUX */
|
||||
print_verilog_comment(fp, std::string("---- Structure-level description -----"));
|
||||
|
@ -177,18 +173,20 @@ void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp,
|
|||
* Generate Verilog codes modeling an branch circuit
|
||||
* for a multiplexer with the given size
|
||||
**********************************************/
|
||||
void generate_verilog_mux_branch_module(std::fstream& fp,
|
||||
static
|
||||
void generate_verilog_mux_branch_module(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
std::fstream& fp,
|
||||
const CircuitModelId& circuit_model,
|
||||
const size_t& mux_size,
|
||||
const MuxGraph& mux_graph) {
|
||||
std::string module_name = generate_verilog_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, verilog_mux_basis_posfix);
|
||||
std::string module_name = generate_verilog_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, mux_graph.num_inputs(), verilog_mux_basis_posfix);
|
||||
|
||||
/* Multiplexers built with different technology is in different organization */
|
||||
switch (circuit_lib.design_tech_type(circuit_model)) {
|
||||
case SPICE_MODEL_DESIGN_CMOS:
|
||||
if (true == circuit_lib.dump_structural_verilog(circuit_model)) {
|
||||
generate_verilog_cmos_mux_branch_module_structural(fp, circuit_lib, circuit_model, module_name, mux_graph);
|
||||
generate_verilog_cmos_mux_branch_module_structural(module_manager, circuit_lib, fp, circuit_model, module_name, mux_graph);
|
||||
} else {
|
||||
/*
|
||||
dump_verilog_cmos_mux_one_basis_module(fp, mux_basis_subckt_name,
|
||||
|
@ -222,3 +220,68 @@ void generate_verilog_mux_branch_module(std::fstream& fp,
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Generate Verilog modules for all the unique
|
||||
* multiplexers in the FPGA device
|
||||
**********************************************/
|
||||
void print_verilog_submodule_muxes(ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
char* verilog_dir,
|
||||
char* submodule_dir) {
|
||||
|
||||
/* TODO: Generate modules into a .bak file now. Rename after it is verified */
|
||||
std::string verilog_fname(my_strcat(submodule_dir, muxes_verilog_file_name));
|
||||
verilog_fname += ".bak";
|
||||
|
||||
/* Create the file stream */
|
||||
std::fstream fp;
|
||||
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
check_file_handler(fp);
|
||||
|
||||
/* Print out debugging information for if the file is not opened/created properly */
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Creating Verilog netlist for Multiplexers (%s) ...\n",
|
||||
verilog_fname.c_str());
|
||||
|
||||
print_verilog_file_header(fp, "Multiplexers");
|
||||
|
||||
print_verilog_include_defines_preproc_file(fp, verilog_dir);
|
||||
|
||||
/* Generate basis sub-circuit for unique branches shared by the multiplexers */
|
||||
for (auto mux : mux_lib.muxes()) {
|
||||
const MuxGraph& mux_graph = mux_lib.mux_graph(mux);
|
||||
CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux);
|
||||
/* Create a mux graph for the branch circuit */
|
||||
std::vector<MuxGraph> branch_mux_graphs = mux_graph.build_mux_branch_graphs();
|
||||
/* Create branch circuits, which are N:1 one-level or 2:1 tree-like MUXes */
|
||||
for (auto branch_mux_graph : branch_mux_graphs) {
|
||||
generate_verilog_mux_branch_module(module_manager, circuit_lib, fp, mux_circuit_model,
|
||||
mux_graph.num_inputs(), branch_mux_graph);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump MUX graph one by one */
|
||||
|
||||
/* Close the file steam */
|
||||
fp.close();
|
||||
|
||||
/* TODO:
|
||||
* Scan-chain configuration circuit does not need any BLs/WLs!
|
||||
* SRAM MUX does not need any reserved BL/WLs!
|
||||
*/
|
||||
/* Determine reserved Bit/Word Lines if a memory bank is specified,
|
||||
* At least 1 BL/WL should be reserved!
|
||||
*/
|
||||
try_update_sram_orgz_info_reserved_blwl(cur_sram_orgz_info,
|
||||
mux_lib.max_mux_size(), mux_lib.max_mux_size());
|
||||
|
||||
/* TODO: Add fname to the linked list when debugging is finished */
|
||||
/*
|
||||
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_name);
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
@ -11,11 +11,13 @@
|
|||
#include "circuit_library.h"
|
||||
#include "mux_graph.h"
|
||||
#include "mux_library.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
void generate_verilog_mux_branch_module(std::fstream& fp,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& circuit_model,
|
||||
const size_t& mux_size,
|
||||
const MuxGraph& mux_graph);
|
||||
void print_verilog_submodule_muxes(ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
char* verilog_dir,
|
||||
char* submodule_dir);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "fpga_x2p_globals.h"
|
||||
#include "fpga_x2p_mux_utils.h"
|
||||
#include "fpga_x2p_bitstream_utils.h"
|
||||
#include "mux_library.h"
|
||||
|
||||
/* Include verilog utils */
|
||||
#include "verilog_global.h"
|
||||
|
@ -2228,11 +2229,13 @@ void dump_verilog_submodule_muxes(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
|
||||
/* Alloc the muxes*/
|
||||
muxes_head = stats_spice_muxes(num_switch, switches, spice, routing_arch);
|
||||
|
||||
|
||||
/* Print the muxes netlist*/
|
||||
fp = fopen(verilog_name, "w");
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create subckt SPICE netlist %s",__FILE__, __LINE__, verilog_name);
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(FILE:%s,LINE[%d])Failure in create subckt SPICE netlist %s",
|
||||
__FILE__, __LINE__, verilog_name);
|
||||
exit(1);
|
||||
}
|
||||
/* Generate the descriptions*/
|
||||
|
@ -2292,41 +2295,6 @@ void dump_verilog_submodule_muxes(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
temp = temp->next;
|
||||
}
|
||||
|
||||
/* Generate modules into a .bak file now. Rename after it is verified */
|
||||
std::string verilog_fname(my_strcat(submodule_dir, muxes_verilog_file_name));
|
||||
verilog_fname += ".bak";
|
||||
|
||||
/* Create the file stream */
|
||||
std::fstream sfp;
|
||||
sfp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
/* Print out debugging information for if the file is not opened/created properly */
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Creating Verilog netlist for Multiplexers (%s) ...\n",
|
||||
verilog_fname.c_str());
|
||||
check_file_handler(sfp);
|
||||
|
||||
/* TODO: this conversion is temporary. Will be removed after code reconstruction */
|
||||
MuxLibrary mux_lib = convert_mux_arch_to_library(spice->circuit_lib, muxes_head);
|
||||
|
||||
/* Generate basis sub-circuit for unique branches shared by the multiplexers */
|
||||
for (auto mux : mux_lib.muxes()) {
|
||||
const MuxGraph& mux_graph = mux_lib.mux_graph(mux);
|
||||
CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux);
|
||||
/* Create a mux graph for the branch circuit */
|
||||
std::vector<MuxGraph> branch_mux_graphs = mux_graph.build_mux_branch_graphs();
|
||||
/* Create branch circuits, which are N:1 one-level or 2:1 tree-like MUXes */
|
||||
for (auto branch_mux_graph : branch_mux_graphs) {
|
||||
generate_verilog_mux_branch_module(sfp, spice->circuit_lib, mux_circuit_model,
|
||||
mux_graph.num_inputs(), branch_mux_graph);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump MUX graph one by one */
|
||||
|
||||
/* Close the file steam */
|
||||
sfp.close();
|
||||
|
||||
/* TODO:
|
||||
* Scan-chain configuration circuit does not need any BLs/WLs!
|
||||
* SRAM MUX does not need any reserved BL/WLs!
|
||||
|
@ -3507,6 +3475,7 @@ void dump_verilog_submodule_templates(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
* 1. MUXes
|
||||
*/
|
||||
void dump_verilog_submodules(ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
char* verilog_dir,
|
||||
char* submodule_dir,
|
||||
|
@ -3514,7 +3483,6 @@ void dump_verilog_submodules(ModuleManager& module_manager,
|
|||
t_det_routing_arch* routing_arch,
|
||||
t_syn_verilog_opts fpga_verilog_opts) {
|
||||
|
||||
/* 0. basic units: inverter, buffers and pass-gate logics, */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Generating essential modules...\n");
|
||||
print_verilog_submodule_essentials(module_manager,
|
||||
std::string(verilog_dir),
|
||||
|
@ -3525,6 +3493,10 @@ void dump_verilog_submodules(ModuleManager& module_manager,
|
|||
vpr_printf(TIO_MESSAGE_INFO, "Generating modules of multiplexers...\n");
|
||||
dump_verilog_submodule_muxes(cur_sram_orgz_info, verilog_dir, submodule_dir, routing_arch->num_switch,
|
||||
switch_inf, Arch.spice, routing_arch, fpga_verilog_opts.dump_explicit_verilog);
|
||||
|
||||
print_verilog_submodule_muxes(module_manager, mux_lib, Arch.spice->circuit_lib, cur_sram_orgz_info,
|
||||
verilog_dir, submodule_dir);
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Generating local encoders for multiplexers...\n");
|
||||
dump_verilog_submodule_local_encoders(cur_sram_orgz_info, verilog_dir, submodule_dir, routing_arch->num_switch,
|
||||
switch_inf, Arch.spice, routing_arch, fpga_verilog_opts.dump_explicit_verilog);
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#define VERILOG_SUBMODULES_H
|
||||
|
||||
#include "module_manager.h"
|
||||
#include "mux_library.h"
|
||||
|
||||
void dump_verilog_submodules(ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
char* verilog_dir,
|
||||
char* submodule_dir,
|
||||
|
|
|
@ -55,7 +55,7 @@ void print_verilog_include_defines_preproc_file(std::fstream& fp,
|
|||
|
||||
fp << "//------ Include defines: preproc flags -----" << std::endl;
|
||||
fp << "`include \"" << include_file_path << "\"" << std::endl;
|
||||
fp << "//------ End Include defines: preproc flags -----" << std::endl;
|
||||
fp << "//------ End Include defines: preproc flags -----" << std::endl << std::endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -102,10 +102,11 @@ void print_verilog_module_ports(std::fstream& fp,
|
|||
for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) {
|
||||
if (0 != port_cnt) {
|
||||
/* Do not dump a comma for the first port */
|
||||
fp << ", //----- " << module_manager.module_port_type_str(kv.first) << " -----" << std::endl;
|
||||
fp << "," << std::endl;
|
||||
}
|
||||
/* Print port */
|
||||
fp << "\t" << generate_verilog_port(kv.second, port) << std::endl;
|
||||
fp << "\t//----- " << module_manager.module_port_type_str(kv.first) << " -----" << std::endl;
|
||||
fp << "\t" << generate_verilog_port(kv.second, port);
|
||||
port_cnt++;
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ void print_verilog_module_declaration(std::fstream& fp,
|
|||
check_file_handler(fp);
|
||||
|
||||
print_verilog_module_definition(fp, module_manager.module_name(module_id));
|
||||
|
||||
|
||||
print_verilog_module_ports(fp, module_manager, module_id);
|
||||
|
||||
fp << std::endl << ");" << std::endl;
|
||||
|
|
Loading…
Reference in New Issue