refactored wire Verilog generation
This commit is contained in:
parent
79fa858f36
commit
2b829238b5
|
@ -94,3 +94,37 @@ std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
|
|||
|
||||
return subckt_name;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Generate the module name of a routing track wire
|
||||
***********************************************/
|
||||
std::string generate_segment_wire_subckt_name(const std::string& wire_model_name,
|
||||
const size_t& segment_id) {
|
||||
std::string segment_wire_subckt_name = wire_model_name + "_seg" + std::to_string(segment_id);
|
||||
|
||||
return segment_wire_subckt_name;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* Generate the port name for the mid-output of a routing track wire
|
||||
* Mid-output is the output that is wired to a Connection block multiplexer.
|
||||
*
|
||||
* | CLB |
|
||||
* +------------+
|
||||
* ^
|
||||
* |
|
||||
* +------------------------------+
|
||||
* | Connection block multiplexer |
|
||||
* +------------------------------+
|
||||
* ^
|
||||
* | mid-output +--------------
|
||||
* +--------------------+ |
|
||||
* input --->| Routing track wire |--------->| Switch Block
|
||||
* +--------------------+ output |
|
||||
* +--------------
|
||||
|
||||
********************************************************************/
|
||||
std::string generate_segment_wire_mid_output_name(const std::string& regular_output_name) {
|
||||
/* TODO: maybe have a postfix? */
|
||||
return std::string("mid_" + regular_output_name);
|
||||
}
|
||||
|
|
|
@ -28,4 +28,9 @@ std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circui
|
|||
std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
|
||||
const size_t& data_size);
|
||||
|
||||
std::string generate_segment_wire_subckt_name(const std::string& wire_model_name,
|
||||
const size_t& segment_id);
|
||||
|
||||
std::string generate_segment_wire_mid_output_name(const std::string& regular_output_name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -162,6 +162,13 @@ ModulePortId ModuleManager::add_port(const ModuleId& module,
|
|||
return port;
|
||||
}
|
||||
|
||||
/* Set a name for a module */
|
||||
void ModuleManager::set_module_name(const ModuleId& module, const std::string& name) {
|
||||
/* Validate the id of module */
|
||||
VTR_ASSERT( valid_module_id(module) );
|
||||
names_[module] = name;
|
||||
}
|
||||
|
||||
/* Set a port to be a register */
|
||||
void ModuleManager::set_port_is_register(const ModuleId& module, const std::string& port_name, const bool& is_register) {
|
||||
/* Find the port */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "vtr_vector.h"
|
||||
#include "module_manager_fwd.h"
|
||||
#include "device_port.h"
|
||||
|
||||
|
@ -53,6 +54,8 @@ class ModuleManager {
|
|||
/* Add a port to a module */
|
||||
ModulePortId add_port(const ModuleId& module,
|
||||
const BasicPort& port_info, const enum e_module_port_type& port_type);
|
||||
/* Set a name for a module */
|
||||
void set_module_name(const ModuleId& module, const std::string& name);
|
||||
/* Set a port to be a register */
|
||||
void set_port_is_register(const ModuleId& module, const std::string& port_name, const bool& is_register);
|
||||
/* Add a child module to a parent module */
|
||||
|
|
|
@ -14,9 +14,17 @@
|
|||
#include "module_manager.h"
|
||||
#include "module_manager_utils.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Add a module to the module manager based on the circuit-level
|
||||
* description of a circuit model
|
||||
* This function add a module with a given customized name
|
||||
* as well as add the ports of circuit model to the module manager
|
||||
******************************************************************************/
|
||||
ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) {
|
||||
ModuleId module = module_manager.add_module(circuit_lib.model_name(circuit_model));
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model,
|
||||
const std::string& module_name) {
|
||||
ModuleId module = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(ModuleId::INVALID() != module);
|
||||
|
||||
/* Add ports */
|
||||
/* Find global ports and add one by one */
|
||||
|
@ -49,3 +57,18 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
|||
/* Return the new id */
|
||||
return module;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Add a module to the module manager based on the circuit-level
|
||||
* description of a circuit model
|
||||
* This function add a module in the name of the circuit model
|
||||
* as well as add the ports of circuit model to the module manager
|
||||
*
|
||||
* This function is a wrapper of a more customizable function in the same name
|
||||
******************************************************************************/
|
||||
ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model) {
|
||||
|
||||
return add_circuit_model_to_module_manager(module_manager, circuit_lib, circuit_model, circuit_lib.model_name(circuit_model));
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,16 @@
|
|||
#ifndef MODULE_MANAGER_UTILS_H
|
||||
#define MODULE_MANAGER_UTILS_H
|
||||
|
||||
/* Include other header files which are dependency on the function declared below */
|
||||
#include "circuit_library.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model,
|
||||
const std::string& module_name);
|
||||
|
||||
ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ void print_verilog_submodule_mux_local_decoders(ModuleManager& module_manager,
|
|||
print_verilog_mux_local_decoder_module(fp, module_manager, decoder_lib, decoder);
|
||||
}
|
||||
|
||||
/* Close the file steam */
|
||||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
||||
/* Add fname to the linked list when debugging is finished */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***********************************************
|
||||
* Header file for verilog_submodule_mux.cpp
|
||||
* Header file for verilog_mux.cpp
|
||||
**********************************************/
|
||||
|
||||
#ifndef VERILOG_MUX_H
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "verilog_essential_gates.h"
|
||||
#include "verilog_decoders.h"
|
||||
#include "verilog_lut.h"
|
||||
#include "verilog_wire.h"
|
||||
|
||||
/***** Subroutines *****/
|
||||
|
||||
|
@ -3351,6 +3352,12 @@ void dump_verilog_submodules(ModuleManager& module_manager,
|
|||
vpr_printf(TIO_MESSAGE_INFO, "Generating modules of hardwires...\n");
|
||||
dump_verilog_submodule_wires(verilog_dir, submodule_dir, Arch.num_segments, Arch.Segments,
|
||||
Arch.spice->num_spice_model, Arch.spice->spice_models);
|
||||
/* Create a vector of segments. TODO: should come from DeviceContext */
|
||||
std::vector<t_segment_inf> L_segment_vec;
|
||||
for (int i = 0; i < Arch.num_segments; ++i) {
|
||||
L_segment_vec.push_back(Arch.Segments[i]);
|
||||
}
|
||||
print_verilog_submodule_wires(module_manager, Arch.spice->circuit_lib, L_segment_vec, std::string(verilog_dir), std::string(submodule_dir));
|
||||
|
||||
/* 4. Memories */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Generating modules of memories...\n");
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
/***********************************************
|
||||
* This file includes functions to generate
|
||||
* Verilog submodules for wires.
|
||||
**********************************************/
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "util.h"
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* Device-level header files */
|
||||
#include "module_manager.h"
|
||||
#include "module_manager_utils.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
|
||||
/* FPGA-X2P context header files */
|
||||
#include "spice_types.h"
|
||||
#include "fpga_x2p_naming.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
|
||||
/* FPGA-Verilog context header files */
|
||||
#include "verilog_global.h"
|
||||
#include "verilog_submodule_utils.h"
|
||||
#include "verilog_writer_utils.h"
|
||||
#include "verilog_wire.h"
|
||||
|
||||
/********************************************************************
|
||||
* Print a Verilog module of a regular wire segment
|
||||
* Regular wire, which is 1-input and 1-output
|
||||
* This type of wires are used in the local routing architecture
|
||||
* +------+
|
||||
* input --->| wire |---> output
|
||||
* +------+
|
||||
*
|
||||
*******************************************************************/
|
||||
static
|
||||
void print_verilog_wire_module(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
std::fstream& fp,
|
||||
const CircuitModelId& wire_model) {
|
||||
/* Ensure a valid file handler*/
|
||||
check_file_handler(fp);
|
||||
|
||||
/* Find the input port, output port*/
|
||||
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||
std::vector<CircuitPortId> global_ports = circuit_lib.model_global_ports_by_type(wire_model, SPICE_MODEL_PORT_INPUT, true, true);
|
||||
|
||||
/* Makre sure the port size is what we want */
|
||||
VTR_ASSERT (1 == input_ports.size());
|
||||
VTR_ASSERT (1 == output_ports.size());
|
||||
VTR_ASSERT (1 == circuit_lib.port_size(input_ports[0]));
|
||||
VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0]));
|
||||
|
||||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId module_id = add_circuit_model_to_module_manager(module_manager, circuit_lib, wire_model);
|
||||
|
||||
/* dump module definition + ports */
|
||||
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||
/* Finish dumping ports */
|
||||
|
||||
/* Print the internal logic of Verilog module */
|
||||
/* Find the input port of the module */
|
||||
ModulePortId module_input_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(input_ports[0]));
|
||||
VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id);
|
||||
BasicPort module_input_port = module_manager.module_port(module_id, module_input_port_id);
|
||||
|
||||
/* Find the output port of the module */
|
||||
ModulePortId module_output_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(output_ports[0]));
|
||||
VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id);
|
||||
BasicPort module_output_port = module_manager.module_port(module_id, module_output_port_id);
|
||||
|
||||
/* Print wire declaration for the inputs and outputs */
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_input_port) << ";" << std::endl;
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_output_port) << ";" << std::endl;
|
||||
|
||||
/* Direct shortcut */
|
||||
print_verilog_wire_connection(fp, module_output_port, module_input_port, false);
|
||||
|
||||
/* Print timing info */
|
||||
print_verilog_submodule_timing(fp, circuit_lib, wire_model);
|
||||
|
||||
/* Put an end to the Verilog module */
|
||||
print_verilog_module_end(fp, circuit_lib.model_name(wire_model));
|
||||
|
||||
/* Add an empty line as a splitter */
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Print a Verilog module of a routing track wire segment
|
||||
* Routing track wire, which is 1-input and dual output
|
||||
* This type of wires are used in the global routing architecture.
|
||||
* One of the output is wired to another Switch block multiplexer,
|
||||
* while the mid-output is wired to a Connection block multiplexer.
|
||||
*
|
||||
* | CLB |
|
||||
* +------------+
|
||||
* ^
|
||||
* |
|
||||
* +------------------------------+
|
||||
* | Connection block multiplexer |
|
||||
* +------------------------------+
|
||||
* ^
|
||||
* | mid-output +--------------
|
||||
* +--------------------+ |
|
||||
* input --->| Routing track wire |--------->| Switch Block
|
||||
* +--------------------+ output |
|
||||
* +--------------
|
||||
*
|
||||
*******************************************************************/
|
||||
static
|
||||
void print_verilog_routing_wire_module(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
std::fstream& fp,
|
||||
const CircuitModelId& wire_model,
|
||||
const std::string& wire_subckt_name) {
|
||||
/* Ensure a valid file handler*/
|
||||
check_file_handler(fp);
|
||||
|
||||
/* Find the input port, output port*/
|
||||
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_INPUT, true);
|
||||
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(wire_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||
|
||||
/* Makre sure the port size is what we want */
|
||||
VTR_ASSERT (1 == input_ports.size());
|
||||
VTR_ASSERT (1 == output_ports.size());
|
||||
VTR_ASSERT (1 == circuit_lib.port_size(input_ports[0]));
|
||||
VTR_ASSERT (1 == circuit_lib.port_size(output_ports[0]));
|
||||
|
||||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId module_id = add_circuit_model_to_module_manager(module_manager, circuit_lib, wire_model, wire_subckt_name);
|
||||
|
||||
/* Add a mid-output port to the module */
|
||||
BasicPort module_mid_output_port(generate_segment_wire_mid_output_name(circuit_lib.port_lib_name(output_ports[0])), circuit_lib.port_size(output_ports[0]));
|
||||
module_manager.add_port(module_id, module_mid_output_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
|
||||
/* dump module definition + ports */
|
||||
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||
/* Finish dumping ports */
|
||||
|
||||
/* Print the internal logic of Verilog module */
|
||||
/* Find the input port of the module */
|
||||
ModulePortId module_input_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(input_ports[0]));
|
||||
VTR_ASSERT(ModulePortId::INVALID() != module_input_port_id);
|
||||
BasicPort module_input_port = module_manager.module_port(module_id, module_input_port_id);
|
||||
|
||||
/* Find the output port of the module */
|
||||
ModulePortId module_output_port_id = module_manager.find_module_port(module_id, circuit_lib.port_lib_name(output_ports[0]));
|
||||
VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id);
|
||||
BasicPort module_output_port = module_manager.module_port(module_id, module_output_port_id);
|
||||
|
||||
/* Print wire declaration for the inputs and outputs */
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_input_port) << ";" << std::endl;
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_output_port) << ";" << std::endl;
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_mid_output_port) << ";" << std::endl;
|
||||
|
||||
/* Direct shortcut */
|
||||
print_verilog_wire_connection(fp, module_output_port, module_input_port, false);
|
||||
print_verilog_wire_connection(fp, module_mid_output_port, module_input_port, false);
|
||||
|
||||
/* Print timing info */
|
||||
print_verilog_submodule_timing(fp, circuit_lib, wire_model);
|
||||
|
||||
/* Put an end to the Verilog module */
|
||||
print_verilog_module_end(fp, circuit_lib.model_name(wire_model));
|
||||
|
||||
/* Add an empty line as a splitter */
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
void print_verilog_submodule_wires(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
std::vector<t_segment_inf> routing_segments,
|
||||
const std::string& verilog_dir,
|
||||
const std::string& submodule_dir) {
|
||||
/* TODO: remove .bak when it is ready to be plugged in */
|
||||
std::string verilog_fname(submodule_dir + wires_verilog_file_name + ".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 wires (%s)...\n",
|
||||
verilog_fname.c_str());
|
||||
|
||||
print_verilog_file_header(fp, "Wires");
|
||||
|
||||
print_verilog_include_defines_preproc_file(fp, verilog_dir);
|
||||
|
||||
/* Print Verilog models for regular wires*/
|
||||
print_verilog_comment(fp, std::string("----- BEGIN Verilog modules for regular wires -----"));
|
||||
for (const auto& model : circuit_lib.models_by_type(SPICE_MODEL_WIRE)) {
|
||||
/* Bypass user-defined circuit models */
|
||||
if (!circuit_lib.model_verilog_netlist(model).empty()) {
|
||||
continue;
|
||||
}
|
||||
print_verilog_wire_module(module_manager, circuit_lib, fp, model);
|
||||
}
|
||||
print_verilog_comment(fp, std::string("----- END Verilog modules for regular wires -----"));
|
||||
|
||||
/* Create wire models for routing segments*/
|
||||
print_verilog_comment(fp, std::string("----- BEGIN Verilog modules for routing track wires -----"));
|
||||
|
||||
for (const auto& seg : routing_segments) {
|
||||
VTR_ASSERT( CircuitModelId::INVALID() != seg.circuit_model);
|
||||
VTR_ASSERT( SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(seg.circuit_model));
|
||||
/* Bypass user-defined circuit models */
|
||||
if (!circuit_lib.model_verilog_netlist(seg.circuit_model).empty()) {
|
||||
continue;
|
||||
}
|
||||
/* Give a unique name for subckt of wire_model of segment,
|
||||
* circuit_model name is unique, and segment id is unique as well
|
||||
*/
|
||||
std::string segment_wire_subckt_name = generate_segment_wire_subckt_name(circuit_lib.model_name(seg.circuit_model), &seg - &routing_segments[0]);
|
||||
|
||||
/* Print a Verilog module */
|
||||
print_verilog_routing_wire_module(module_manager, circuit_lib, fp, seg.circuit_model, segment_wire_subckt_name);
|
||||
}
|
||||
print_verilog_comment(fp, std::string("----- END Verilog modules for routing track wires -----"));
|
||||
|
||||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
||||
/* Add fname to the linked list */
|
||||
/* Uncomment this when it is ready to be plugged in
|
||||
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str());
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/***********************************************
|
||||
* Header file for verilog_wire.cpp
|
||||
**********************************************/
|
||||
|
||||
#ifndef VERILOG_WIRE_H
|
||||
#define VERILOG_WIRE_H
|
||||
|
||||
/* Include other header files which are dependency on the function declared below */
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
void print_verilog_submodule_wires(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
std::vector<t_segment_inf> routing_segments,
|
||||
const std::string& verilog_dir,
|
||||
const std::string& submodule_dir);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue