refactoring local encoders. Ready to plug in
This commit is contained in:
parent
59edd49862
commit
62853c092f
|
@ -253,7 +253,7 @@ enum e_spice_model_pass_gate_logic_type CircuitLibrary::pass_gate_logic_type(con
|
|||
return pass_gate_logic_types_[model_id];
|
||||
}
|
||||
|
||||
/* Return the multiplex structure of a circuit model */
|
||||
/* Return the type of multiplexing structure of a circuit model */
|
||||
enum e_spice_model_structure CircuitLibrary::mux_structure(const CircuitModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
|
@ -263,7 +263,7 @@ enum e_spice_model_structure CircuitLibrary::mux_structure(const CircuitModelId&
|
|||
return mux_structure_[model_id];
|
||||
}
|
||||
|
||||
|
||||
/* Return the number of levels of multiplexing structure of a circuit model */
|
||||
size_t CircuitLibrary::mux_num_levels(const CircuitModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
|
@ -275,7 +275,7 @@ size_t CircuitLibrary::mux_num_levels(const CircuitModelId& model_id) const {
|
|||
}
|
||||
|
||||
/* Return if additional constant inputs are required for a circuit model
|
||||
* Only applicable for MUX circuit model
|
||||
* Only applicable for MUX/LUT circuit model
|
||||
*/
|
||||
bool CircuitLibrary::mux_add_const_input(const CircuitModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
|
@ -288,7 +288,7 @@ bool CircuitLibrary::mux_add_const_input(const CircuitModelId& model_id) const {
|
|||
}
|
||||
|
||||
/* Return if additional constant inputs are required for a circuit model
|
||||
* Only applicable for MUX circuit model
|
||||
* Only applicable for MUX/LUT circuit model
|
||||
*/
|
||||
size_t CircuitLibrary::mux_const_input_value(const CircuitModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
|
@ -302,6 +302,18 @@ size_t CircuitLibrary::mux_const_input_value(const CircuitModelId& model_id) con
|
|||
return mux_const_input_values_[model_id];
|
||||
}
|
||||
|
||||
/* Return if local encoders are used for a circuit model
|
||||
* Only applicable for MUX/LUT circuit model
|
||||
*/
|
||||
bool CircuitLibrary::mux_use_local_encoder(const CircuitModelId& model_id) const {
|
||||
/* validate the model_id */
|
||||
VTR_ASSERT(valid_model_id(model_id));
|
||||
/* validate the circuit model type is MUX */
|
||||
VTR_ASSERT( (SPICE_MODEL_MUX == model_type(model_id))
|
||||
|| (SPICE_MODEL_LUT == model_type(model_id)) );
|
||||
return mux_use_local_encoder_[model_id];
|
||||
}
|
||||
|
||||
/* Return the type of gate for a circuit model
|
||||
* Only applicable for GATE circuit model
|
||||
*/
|
||||
|
|
|
@ -236,6 +236,7 @@ class CircuitLibrary {
|
|||
size_t mux_num_levels(const CircuitModelId& model_id) const;
|
||||
bool mux_add_const_input(const CircuitModelId& model_id) const;
|
||||
size_t mux_const_input_value(const CircuitModelId& model_id) const;
|
||||
bool mux_use_local_encoder(const CircuitModelId& model_id) const;
|
||||
/* Gate information */
|
||||
enum e_spice_model_gate_type gate_type(const CircuitModelId& model_id) const;
|
||||
/* Buffer information */
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/***************************************************************************************
|
||||
* This file includes memeber functions for data structure DecoderLibrary
|
||||
**************************************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
#include "decoder_library.h"
|
||||
|
||||
/***************************************************************************************
|
||||
* Public Accessors: Aggregators
|
||||
**************************************************************************************/
|
||||
DecoderLibrary::decoder_range DecoderLibrary::decoders() const {
|
||||
return vtr::make_range(decoder_ids_.begin(), decoder_ids_.end());
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
* Public Accessors: Data query
|
||||
**************************************************************************************/
|
||||
/* Get the size of address input of a decoder */
|
||||
size_t DecoderLibrary::addr_size(const DecoderId& decoder) const {
|
||||
VTR_ASSERT_SAFE(valid_decoder_id(decoder));
|
||||
return addr_sizes_[decoder];
|
||||
}
|
||||
|
||||
/* Get the size of data output of a decoder */
|
||||
size_t DecoderLibrary::data_size(const DecoderId& decoder) const {
|
||||
VTR_ASSERT_SAFE(valid_decoder_id(decoder));
|
||||
return data_sizes_[decoder];
|
||||
}
|
||||
|
||||
/* Get the flag if a decoder includes an ENABLE signal */
|
||||
bool DecoderLibrary::use_enable(const DecoderId& decoder) const {
|
||||
VTR_ASSERT_SAFE(valid_decoder_id(decoder));
|
||||
return use_enable_[decoder];
|
||||
}
|
||||
|
||||
/* Get the flag if a decoder includes an DATA_IN signal */
|
||||
bool DecoderLibrary::use_data_in(const DecoderId& decoder) const {
|
||||
VTR_ASSERT_SAFE(valid_decoder_id(decoder));
|
||||
return use_data_in_[decoder];
|
||||
}
|
||||
|
||||
/* Get the flag if a decoder includes a data_inv port which is an inversion of the regular data output port */
|
||||
bool DecoderLibrary::use_data_inv_port(const DecoderId& decoder) const {
|
||||
VTR_ASSERT_SAFE(valid_decoder_id(decoder));
|
||||
return use_data_inv_port_[decoder];
|
||||
}
|
||||
|
||||
/* Find a decoder to the library, with the specification.
|
||||
* If found, return the id of decoder.
|
||||
* If not found, return an invalid id of decoder
|
||||
* To avoid duplicated decoders, this function should be used before adding a decoder
|
||||
* Example:
|
||||
* DecoderId decoder_id == decoder_lib.find_decoder();
|
||||
* if (DecoderId::INVALID() == decoder_id) {
|
||||
* // Add decoder
|
||||
* }
|
||||
*/
|
||||
DecoderId DecoderLibrary::find_decoder(const size_t& addr_size,
|
||||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port) const {
|
||||
for (auto decoder : decoders()) {
|
||||
if ( (addr_size == addr_sizes_[decoder])
|
||||
&& (data_size == data_sizes_[decoder])
|
||||
&& (use_enable == use_enable_[decoder])
|
||||
&& (use_data_in == use_data_in_[decoder])
|
||||
&& (use_data_inv_port == use_data_inv_port_[decoder]) ) {
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found, return an invalid id by default */
|
||||
return DecoderId::INVALID();
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
* Public Validators
|
||||
**************************************************************************************/
|
||||
/* Validate ids */
|
||||
bool DecoderLibrary::valid_decoder_id(const DecoderId& decoder) const {
|
||||
return size_t(decoder) < decoder_ids_.size() && decoder_ids_[decoder] == decoder;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
* Public Mutators : Basic Operations
|
||||
**************************************************************************************/
|
||||
/* Add a decoder to the library */
|
||||
DecoderId DecoderLibrary::add_decoder(const size_t& addr_size,
|
||||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port) {
|
||||
DecoderId decoder = DecoderId(decoder_ids_.size());
|
||||
/* Push to the decoder list */
|
||||
decoder_ids_.push_back(decoder);
|
||||
/* Resize the other related vectors */
|
||||
addr_sizes_.push_back(addr_size);
|
||||
data_sizes_.push_back(data_size);
|
||||
use_enable_.push_back(use_enable);
|
||||
use_data_in_.push_back(use_data_in);
|
||||
use_data_inv_port_.push_back(use_data_inv_port);
|
||||
|
||||
return decoder;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/***************************************************************************************
|
||||
* This file includes key data structures to describe decoders which are used
|
||||
* in FPGA fabrics
|
||||
* A decoder is a circuit to convert a binary input to one-hot codes
|
||||
* The outputs are assumes to be one-hot codes (at most only one '1' exist)
|
||||
* Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2))
|
||||
* All the decoders are assumed to follow the port map :
|
||||
*
|
||||
* Inputs
|
||||
* | | ... |
|
||||
* v v v
|
||||
* +-----------+
|
||||
* / \
|
||||
* / Decoder \
|
||||
* +-----------------+
|
||||
* | | | ... | | |
|
||||
* v v v v v v
|
||||
* Outputs
|
||||
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef DECODER_LIBRARY_H
|
||||
#define DECODER_LIBRARY_H
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_range.h"
|
||||
#include "decoder_library_fwd.h"
|
||||
|
||||
class DecoderLibrary {
|
||||
public: /* Types and ranges */
|
||||
typedef vtr::vector<DecoderId, DecoderId>::const_iterator decoder_iterator;
|
||||
|
||||
typedef vtr::Range<decoder_iterator> decoder_range;
|
||||
|
||||
public: /* Public accessors: Aggregates */
|
||||
/* Get all the decoders */
|
||||
decoder_range decoders() const;
|
||||
|
||||
public: /* Public accessors: Data query */
|
||||
/* Get the size of address input of a decoder */
|
||||
size_t addr_size(const DecoderId& decoder) const;
|
||||
/* Get the size of data output of a decoder */
|
||||
size_t data_size(const DecoderId& decoder) const;
|
||||
/* Get the flag if a decoder includes an ENABLE signal */
|
||||
bool use_enable(const DecoderId& decoder) const;
|
||||
/* Get the flag if a decoder includes an DATA_IN signal */
|
||||
bool use_data_in(const DecoderId& decoder) const;
|
||||
/* Get the flag if a decoder includes a data_inv port which is an inversion of the regular data output port */
|
||||
bool use_data_inv_port(const DecoderId& decoder) const;
|
||||
/* Find a decoder to the library, with the specification.
|
||||
* If found, return the id of decoder.
|
||||
* If not found, return an invalid id of decoder
|
||||
* To avoid duplicated decoders, this function should be used before adding a decoder
|
||||
* Example:
|
||||
* DecoderId decoder_id == decoder_lib.find_decoder();
|
||||
* if (DecoderId::INVALID() == decoder_id) {
|
||||
* // Add decoder
|
||||
* }
|
||||
*/
|
||||
DecoderId find_decoder(const size_t& addr_size,
|
||||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port) const;
|
||||
|
||||
public: /* Public validators */
|
||||
/* valid ids */
|
||||
bool valid_decoder_id(const DecoderId& decoder) const;
|
||||
|
||||
public: /* Private mutators : basic operations */
|
||||
/* Add a decoder to the library */
|
||||
DecoderId add_decoder(const size_t& addr_size,
|
||||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port);
|
||||
|
||||
private: /* Internal Data */
|
||||
vtr::vector<DecoderId, DecoderId> decoder_ids_;
|
||||
vtr::vector<DecoderId, size_t> addr_sizes_;
|
||||
vtr::vector<DecoderId, size_t> data_sizes_;
|
||||
vtr::vector<DecoderId, bool> use_enable_;
|
||||
vtr::vector<DecoderId, bool> use_data_in_;
|
||||
vtr::vector<DecoderId, bool> use_data_inv_port_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/**************************************************
|
||||
* This file includes only declarations for
|
||||
* the data structures to describe decoders
|
||||
* Please refer to decoder_library.h for more details
|
||||
*************************************************/
|
||||
#ifndef DECODER_LIBRARY_FWD_H
|
||||
#define DECODER_LIBRARY_FWD_H
|
||||
|
||||
#include "vtr_strong_id.h"
|
||||
|
||||
/* Strong Ids for MUXes */
|
||||
struct decoder_id_tag;
|
||||
|
||||
typedef vtr::StrongId<decoder_id_tag> DecoderId;
|
||||
|
||||
class DecoderLibrary;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,53 @@
|
|||
/***************************************************************************************
|
||||
* This file includes most utilized functions for the DecoderLibrary data structure
|
||||
***************************************************************************************/
|
||||
#include <cmath>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "decoder_library_utils.h"
|
||||
|
||||
/***************************************************************************************
|
||||
* NOTE: This function is mainly designed for local decoders inside multiplexers
|
||||
* Find the size of address lines for a decoder with a given data output size
|
||||
* Addr lines
|
||||
* | | ... |
|
||||
* v v v
|
||||
* +-----------+
|
||||
* / Local \
|
||||
* / Decoder \
|
||||
* +-----------------+
|
||||
* | | | ... | | |
|
||||
* v v v v v v
|
||||
* Data outputs
|
||||
*
|
||||
* The outputs are assumes to be one-hot codes (at most only one '1' exist)
|
||||
* Considering this fact, there are only num_of_outputs + 1 conditions to be encoded.
|
||||
* Therefore, the number of inputs is ceil(log(num_of_outputs+1)/log(2))
|
||||
* We plus 1, which is all-zero condition for outputs
|
||||
***************************************************************************************/
|
||||
size_t find_mux_local_decoder_addr_size(const size_t& data_size) {
|
||||
/* Make sure we have a encoder which is at least 2 ! */
|
||||
VTR_ASSERT (2 <= data_size);
|
||||
return ceil(log(data_size) / log(2));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
* Try to find if the decoder already exists in the library,
|
||||
* If there is no such decoder, add it to the library
|
||||
***************************************************************************************/
|
||||
DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib,
|
||||
const size_t data_size) {
|
||||
size_t addr_size = find_mux_local_decoder_addr_size(data_size);
|
||||
|
||||
DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true);
|
||||
|
||||
if (DecoderId::INVALID() == decoder_id) {
|
||||
/* Add the decoder */
|
||||
return decoder_lib.add_decoder(addr_size, data_size, false, false, true);
|
||||
}
|
||||
|
||||
/* There is already a decoder in the library, return the decoder id */
|
||||
return decoder_id;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/***************************************************************************************
|
||||
* Header file for most utilized functions for the DecoderLibrary data structure
|
||||
***************************************************************************************/
|
||||
#ifndef DECODER_LIBRARY_UTILS_H
|
||||
#define DECODER_LIBRARY_UTILS_H
|
||||
|
||||
#include "decoder_library.h"
|
||||
|
||||
size_t find_mux_local_decoder_addr_size(const size_t& data_size);
|
||||
|
||||
DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib,
|
||||
const size_t data_size);
|
||||
|
||||
#endif
|
|
@ -1,8 +1,11 @@
|
|||
/************************************************
|
||||
/********************************************************************
|
||||
* This file includes functions to
|
||||
* generate module/port names for Verilog
|
||||
* and SPICE netlists
|
||||
***********************************************/
|
||||
*
|
||||
* IMPORTANT: keep all the naming functions in this file to be
|
||||
* generic for both Verilog and SPICE generators
|
||||
********************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "fpga_x2p_naming.h"
|
||||
|
@ -77,3 +80,17 @@ std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circui
|
|||
|
||||
return generate_verilog_mux_subckt_name(circuit_lib, circuit_model, mux_size, branch_postfix);
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Generate the module name of a local decoder
|
||||
* for multiplexer
|
||||
***********************************************/
|
||||
std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
|
||||
const size_t& data_size) {
|
||||
std::string subckt_name = "decoder";
|
||||
subckt_name += std::to_string(addr_size);
|
||||
subckt_name += "to";
|
||||
subckt_name += std::to_string(data_size);
|
||||
|
||||
return subckt_name;
|
||||
}
|
||||
|
|
|
@ -25,4 +25,7 @@ std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circui
|
|||
const size_t& branch_mux_size,
|
||||
const std::string& posfix);
|
||||
|
||||
std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
|
||||
const size_t& data_size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "vtr_assert.h"
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
|
@ -632,6 +633,22 @@ char* my_ito1hot(int in_int, int bin_len) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Convert an integer to an one-hot encoding integer array */
|
||||
std::vector<size_t> my_ito1hot_vec(const size_t& in_int, const size_t& bin_len) {
|
||||
/* Make sure we do not have any overflow! */
|
||||
VTR_ASSERT ( (in_int <= bin_len) );
|
||||
|
||||
/* Initialize */
|
||||
std::vector<size_t> ret(bin_len, 0);
|
||||
|
||||
if (bin_len == in_int) {
|
||||
return ret; /* all zero case */
|
||||
}
|
||||
ret[in_int] = 1; /* Keep a good sequence of bits */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Converter an integer to a binary string */
|
||||
int* my_itobin_int(int in_int, int bin_len) {
|
||||
int* ret = (int*) my_calloc (bin_len, sizeof(int));
|
||||
|
@ -652,6 +669,24 @@ int* my_itobin_int(int in_int, int bin_len) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Converter an integer to a binary vector */
|
||||
std::vector<size_t> my_itobin_vec(const size_t& in_int, const size_t& bin_len) {
|
||||
std::vector<size_t> ret(bin_len, 0);
|
||||
|
||||
/* Make sure we do not have any overflow! */
|
||||
VTR_ASSERT ( (in_int < pow(2., bin_len)) );
|
||||
|
||||
size_t temp = in_int;
|
||||
for (size_t i = 0; i < bin_len; i++) {
|
||||
if (1 == temp % 2) {
|
||||
ret[i] = 1; /* Keep a good sequence of bits */
|
||||
}
|
||||
temp = temp / 2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Converter an integer to a binary string */
|
||||
char* my_itobin(int in_int, int bin_len) {
|
||||
char* ret = (char*) my_calloc (bin_len + 1, sizeof(char));
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define FPGA_X2P_UTILS_H
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "my_free_fwd.h"
|
||||
#include "rr_blocks_naming.h"
|
||||
|
@ -65,10 +66,14 @@ t_spice_transistor_type* find_mosfet_tech_lib(t_spice_tech_lib tech_lib,
|
|||
|
||||
char* my_ito1hot(int in_int, int bin_len);
|
||||
|
||||
std::vector<size_t> my_ito1hot_vec(const size_t& in_int, const size_t& bin_len);
|
||||
|
||||
char* my_itobin(int in_int, int bin_len);
|
||||
|
||||
int* my_itobin_int(int in_int, int bin_len);
|
||||
|
||||
std::vector<size_t> my_itobin_vec(const size_t& in_int, const size_t& bin_len);
|
||||
|
||||
char* my_itoa(int input);
|
||||
|
||||
char* fpga_spice_create_one_subckt_filename(const char* file_name_prefix,
|
||||
|
|
|
@ -99,6 +99,13 @@ size_t ModuleManager::num_instance(const ModuleId& parent_module, const ModuleId
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Find if a port is register */
|
||||
bool ModuleManager::port_is_register(const ModuleId& module, const ModulePortId& port) const {
|
||||
/* validate both module id and port id*/
|
||||
VTR_ASSERT(valid_module_port_id(module, port));
|
||||
return port_is_register_[module][port];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public Mutators
|
||||
******************************************************************************/
|
||||
|
@ -123,6 +130,7 @@ ModuleId ModuleManager::add_module(const std::string& name) {
|
|||
port_ids_.emplace_back();
|
||||
ports_.emplace_back();
|
||||
port_types_.emplace_back();
|
||||
port_is_register_.emplace_back();
|
||||
|
||||
/* Register in the name-to-id map */
|
||||
name_id_map_[name] = module;
|
||||
|
@ -146,6 +154,7 @@ ModulePortId ModuleManager::add_port(const ModuleId& module,
|
|||
port_ids_[module].push_back(port);
|
||||
ports_[module].push_back(port_info);
|
||||
port_types_[module].push_back(port_type);
|
||||
port_is_register_[module].push_back(false);
|
||||
|
||||
/* Update fast look-up for port */
|
||||
port_lookup_[module][port_type].push_back(port);
|
||||
|
@ -153,6 +162,15 @@ ModulePortId ModuleManager::add_port(const ModuleId& module,
|
|||
return port;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
ModulePortId port = find_module_port(module, port_name);
|
||||
/* Must find something, otherwise drop an error */
|
||||
VTR_ASSERT(ModulePortId::INVALID() != port);
|
||||
port_is_register_[module][port] = is_register;
|
||||
}
|
||||
|
||||
/* Add a child module to a parent module */
|
||||
void ModuleManager::add_child_module(const ModuleId& parent_module, const ModuleId& child_module) {
|
||||
/* Validate the id of both parent and child modules */
|
||||
|
|
|
@ -45,12 +45,16 @@ class ModuleManager {
|
|||
ModuleId find_module(const std::string& name) const;
|
||||
/* Find the number of instances of a child module in the parent module */
|
||||
size_t num_instance(const ModuleId& parent_module, const ModuleId& child_module) const;
|
||||
/* Find if a port is register */
|
||||
bool port_is_register(const ModuleId& module, const ModulePortId& port) const;
|
||||
public: /* Public mutators */
|
||||
/* Add a module */
|
||||
ModuleId add_module(const std::string& name);
|
||||
/* 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 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 */
|
||||
void add_child_module(const ModuleId& parent_module, const ModuleId& child_module);
|
||||
private: /* Private validators/invalidators */
|
||||
|
@ -68,6 +72,7 @@ class ModuleManager {
|
|||
vtr::vector<ModuleId, vtr::vector<ModulePortId, ModulePortId>> port_ids_; /* List of ports for each Module */
|
||||
vtr::vector<ModuleId, vtr::vector<ModulePortId, BasicPort>> ports_; /* List of ports for each Module */
|
||||
vtr::vector<ModuleId, vtr::vector<ModulePortId, enum e_module_port_type>> port_types_; /* Type of ports */
|
||||
vtr::vector<ModuleId, vtr::vector<ModulePortId, bool>> port_is_register_; /* If the port is a register, use for Verilog port definition. If enabled: <port_type> reg <port_name> */
|
||||
|
||||
/* fast look-up for module */
|
||||
std::map<std::string, ModuleId> name_id_map_;
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
/***************************************************************************************
|
||||
* This file includes functions to generate Verilog modules of decoders
|
||||
***************************************************************************************/
|
||||
/* TODO: merge verilog_decoder.c to this source file and rename to verilog_decoder.cpp */
|
||||
#include <string>
|
||||
|
||||
#include "util.h"
|
||||
#include "vtr_assert.h"
|
||||
|
||||
/* Device-level header files */
|
||||
#include "decoder_library_utils.h"
|
||||
#include "module_manager.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_writer_utils.h"
|
||||
#include "verilog_decoders.h"
|
||||
|
||||
/***************************************************************************************
|
||||
* Create a Verilog module for a decoder with a given output size
|
||||
*
|
||||
* Inputs
|
||||
* | | ... |
|
||||
* v v v
|
||||
* +-----------+
|
||||
* / \
|
||||
* / Decoder \
|
||||
* +-----------------+
|
||||
* | | | ... | | |
|
||||
* v v v v v v
|
||||
* Outputs
|
||||
*
|
||||
* The outputs are assumes to be one-hot codes (at most only one '1' exist)
|
||||
* Considering this fact, there are only num_of_outputs conditions to be encoded.
|
||||
* Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2))
|
||||
***************************************************************************************/
|
||||
static
|
||||
void print_verilog_mux_local_decoder_module(std::fstream& fp,
|
||||
ModuleManager& module_manager,
|
||||
const DecoderLibrary& decoder_lib,
|
||||
const DecoderId& decoder) {
|
||||
/* Get the number of inputs */
|
||||
size_t addr_size = decoder_lib.addr_size(decoder);
|
||||
size_t data_size = decoder_lib.data_size(decoder);
|
||||
|
||||
/* Validate the FILE handler */
|
||||
check_file_handler(fp);
|
||||
|
||||
/* TODO: create a name for the local encoder */
|
||||
std::string module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size);
|
||||
|
||||
/* 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 input port */
|
||||
BasicPort addr_port("addr", addr_size);
|
||||
module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
/* Add each output port */
|
||||
BasicPort data_port("data", data_size);
|
||||
module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
/* Data port is registered. It should be outputted as
|
||||
* output reg [lsb:msb] data
|
||||
*/
|
||||
module_manager.set_port_is_register(module_id, data_port.get_name(), true);
|
||||
/* Add data_in port */
|
||||
BasicPort data_inv_port("data_inv", data_size);
|
||||
VTR_ASSERT(true == decoder_lib.use_data_inv_port(decoder));
|
||||
module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
|
||||
/* dump module definition + ports */
|
||||
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||
/* Finish dumping ports */
|
||||
|
||||
print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
|
||||
|
||||
/* Print the truth table of this decoder */
|
||||
/* Internal logics */
|
||||
/* We use a magic number -1 as the addr=1 should be mapped to ...1
|
||||
* Otherwise addr will map addr=1 to ..10
|
||||
* Note that there should be a range for the shift operators
|
||||
* We should narrow the encoding to be applied to a given set of data
|
||||
* This will lead to that any addr which falls out of the op code of data
|
||||
* will give a all-zero code
|
||||
* For example:
|
||||
* data is 5-bit while addr is 3-bit
|
||||
* data=8'b0_0000 will be encoded to addr=3'b001;
|
||||
* data=8'b0_0001 will be encoded to addr=3'b010;
|
||||
* data=8'b0_0010 will be encoded to addr=3'b011;
|
||||
* data=8'b0_0100 will be encoded to addr=3'b100;
|
||||
* data=8'b0_1000 will be encoded to addr=3'b101;
|
||||
* data=8'b1_0000 will be encoded to addr=3'b110;
|
||||
* The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000;
|
||||
*/
|
||||
|
||||
fp << "\t" << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
|
||||
fp << "\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
|
||||
/* Create a string for addr and data */
|
||||
for (size_t i = 0; i < data_size; ++i) {
|
||||
/* TODO: give a namespace to the itobin function */
|
||||
fp << "\t\t" << generate_verilog_constant_values(my_itobin_vec(i, addr_size));
|
||||
fp << " : ";
|
||||
fp << generate_verilog_port_constant_values(data_port, my_ito1hot_vec(i, data_size));
|
||||
fp << ";" << std::endl;
|
||||
}
|
||||
fp << "\t\t" << "default : ";
|
||||
fp << generate_verilog_port_constant_values(data_port, my_ito1hot_vec(data_size - 1, data_size));
|
||||
fp << ";" << std::endl;
|
||||
fp << "\t" << "endcase" << std::endl;
|
||||
|
||||
print_verilog_wire_connection(fp, data_inv_port, data_port, true);
|
||||
|
||||
print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
|
||||
|
||||
/* Put an end to the Verilog module */
|
||||
print_verilog_module_end(fp, module_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
* This function will generate all the unique Verilog modules of local decoders for
|
||||
* the multiplexers used in a FPGA fabric
|
||||
* It will reach the goal in two steps:
|
||||
* 1. Find the unique local decoders w.r.t. the number of inputs/outputs
|
||||
* We will generate the subgraphs from the multiplexing graph of each multiplexers
|
||||
* The number of memory bits is the number of outputs.
|
||||
* From that we can infer the number of inputs of each local decoders.
|
||||
* Here is an illustrative example of how local decoders are interfaced with multi-level MUXes
|
||||
*
|
||||
* +---------+ +---------+
|
||||
* | Local | | Local |
|
||||
* | Decoder | | Decoder |
|
||||
* | A | | B |
|
||||
* +---------+ +---------+
|
||||
* | ... | | ... |
|
||||
* v v v v
|
||||
* +--------------+ +--------------+
|
||||
* | MUX Level 0 |--->| MUX Level 1 |
|
||||
* +--------------+ +--------------+
|
||||
* 2. Generate local decoder Verilog modules using behavioral description.
|
||||
* Note that the implementation of local decoders can be dependent on the technology
|
||||
* and standard cell libraries.
|
||||
* Therefore, behavioral Verilog is used and the local decoders should be synthesized
|
||||
* before running the back-end flow for FPGA fabric
|
||||
* See more details in the function print_verilog_mux_local_decoder() for more details
|
||||
***************************************************************************************/
|
||||
void print_verilog_submodule_mux_local_decoders(ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::string& verilog_dir,
|
||||
const std::string& submodule_dir) {
|
||||
|
||||
/* TODO: Generate modules into a .bak file now. Rename after it is verified */
|
||||
std::string verilog_fname(submodule_dir + local_encoder_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 local decoders for multiplexers (%s)...\n",
|
||||
verilog_fname.c_str());
|
||||
|
||||
print_verilog_file_header(fp, "Local Decoders for Multiplexers");
|
||||
|
||||
print_verilog_include_defines_preproc_file(fp, verilog_dir);
|
||||
|
||||
/* Create a library for local encoders with different sizes */
|
||||
DecoderLibrary decoder_lib;
|
||||
|
||||
/* Find unique local decoders for unique branches shared by the multiplexers */
|
||||
for (auto mux : mux_lib.muxes()) {
|
||||
/* Local decoders are need only when users specify them */
|
||||
CircuitModelId mux_circuit_model = mux_lib.mux_circuit_model(mux);
|
||||
/* If this MUX does not need local decoder, we skip it */
|
||||
if (false == circuit_lib.mux_use_local_encoder(mux_circuit_model)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const MuxGraph& mux_graph = mux_lib.mux_graph(mux);
|
||||
/* Create a mux graph for the branch circuit */
|
||||
std::vector<MuxGraph> branch_mux_graphs = mux_graph.build_mux_branch_graphs();
|
||||
/* Add the decoder to the decoder library */
|
||||
for (auto branch_mux_graph : branch_mux_graphs) {
|
||||
/* Try to find if the decoder already exists in the library,
|
||||
* If there is no such decoder, add it to the library
|
||||
*/
|
||||
add_mux_local_decoder_to_library(decoder_lib, branch_mux_graph.num_inputs());
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate Verilog modules for the found unique local encoders */
|
||||
for (const auto& decoder : decoder_lib.decoders()) {
|
||||
print_verilog_mux_local_decoder_module(fp, module_manager, decoder_lib, decoder);
|
||||
}
|
||||
|
||||
/* Close the file steam */
|
||||
fp.close();
|
||||
|
||||
/* 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);
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/***************************************************************************************
|
||||
* Header file for verilog_decoders.cpp
|
||||
***************************************************************************************/
|
||||
/* TODO: merge to verilog_decoder.h */
|
||||
|
||||
#ifndef VERILOG_DECODERS_H
|
||||
#define VERILOG_DECODERS_H
|
||||
|
||||
/* Include other header files which are dependency on the function declared below */
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "circuit_library.h"
|
||||
#include "mux_graph.h"
|
||||
#include "mux_library.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
void print_verilog_submodule_mux_local_decoders(ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::string& verilog_dir,
|
||||
const std::string& submodule_dir);
|
||||
|
||||
#endif
|
|
@ -1176,7 +1176,7 @@ void generate_verilog_cmos_mux_module_input_buffers(ModuleManager& module_manage
|
|||
print_verilog_comment(fp, std::string("---- BEGIN short-wire a multiplexing structure input to MUX module input -----"));
|
||||
|
||||
/* Short wire all the datapath inputs to the MUX inputs */
|
||||
print_verilog_wire_connection(fp, instance_output_port, instance_input_port);
|
||||
print_verilog_wire_connection(fp, instance_output_port, instance_input_port, false);
|
||||
|
||||
print_verilog_comment(fp, std::string("---- END short-wire a multiplexing structure input to MUX module input -----"));
|
||||
fp << std::endl;
|
||||
|
@ -1255,7 +1255,7 @@ void generate_verilog_cmos_mux_module_output_buffers(ModuleManager& module_manag
|
|||
print_verilog_comment(fp, std::string("---- BEGIN short-wire a multiplexing structure output to MUX module output -----"));
|
||||
|
||||
/* Short wire all the datapath inputs to the MUX inputs */
|
||||
print_verilog_wire_connection(fp, instance_output_port, instance_input_port);
|
||||
print_verilog_wire_connection(fp, instance_output_port, instance_input_port, false);
|
||||
|
||||
print_verilog_comment(fp, std::string("---- END short-wire a multiplexing structure output to MUX module output -----"));
|
||||
fp << std::endl;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "mux_utils.h"
|
||||
#include "verilog_mux.h"
|
||||
#include "verilog_essential_gates.h"
|
||||
#include "verilog_decoders.h"
|
||||
|
||||
/***** Subroutines *****/
|
||||
|
||||
|
@ -3561,6 +3562,8 @@ void dump_verilog_submodules(ModuleManager& module_manager,
|
|||
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);
|
||||
|
||||
print_verilog_submodule_mux_local_decoders(module_manager, mux_lib, Arch.spice->circuit_lib, std::string(verilog_dir), std::string(submodule_dir));
|
||||
|
||||
/* 2. LUTes */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Generating modules of LUTs...\n");
|
||||
dump_verilog_submodule_luts(verilog_dir, submodule_dir,
|
||||
|
|
|
@ -72,13 +72,45 @@ void print_verilog_comment(std::fstream& fp,
|
|||
|
||||
/************************************************
|
||||
* Print a Verilog module definition
|
||||
* We use the following format:
|
||||
* module <module_name> (<ports without directions>);
|
||||
***********************************************/
|
||||
void print_verilog_module_definition(std::fstream& fp,
|
||||
const std::string& module_name) {
|
||||
const ModuleManager& module_manager, const ModuleId& module_id) {
|
||||
check_file_handler(fp);
|
||||
|
||||
print_verilog_comment(fp, std::string("----- Verilog module for " + module_name + " -----"));
|
||||
fp << "module " << module_name << "(" << std::endl;
|
||||
print_verilog_comment(fp, std::string("----- Verilog module for " + module_manager.module_name(module_id) + " -----"));
|
||||
|
||||
std::string module_head_line = "module " + module_manager.module_name(module_id) + "(";
|
||||
fp << module_head_line;
|
||||
|
||||
/* port type2type mapping */
|
||||
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
|
||||
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT;
|
||||
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT;
|
||||
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT;
|
||||
port_type2type_map[ModuleManager::MODULE_OUTPUT_PORT] = VERILOG_PORT_CONKT;
|
||||
port_type2type_map[ModuleManager::MODULE_CLOCK_PORT] = VERILOG_PORT_CONKT;
|
||||
|
||||
/* Port sequence: global, inout, input, output and clock ports, */
|
||||
size_t port_cnt = 0;
|
||||
for (const auto& kv : port_type2type_map) {
|
||||
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 << "," << std::endl;
|
||||
}
|
||||
/* Create a space for "module <module_name>" except the first line! */
|
||||
if (0 != port_cnt) {
|
||||
std::string port_whitespace(module_head_line.length(), ' ');
|
||||
fp << port_whitespace;
|
||||
}
|
||||
/* Print port */
|
||||
fp << generate_verilog_port(kv.second, port);
|
||||
port_cnt++;
|
||||
}
|
||||
}
|
||||
fp << ");" << std::endl;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
|
@ -97,33 +129,45 @@ void print_verilog_module_ports(std::fstream& fp,
|
|||
port_type2type_map[ModuleManager::MODULE_CLOCK_PORT] = VERILOG_PORT_INPUT;
|
||||
|
||||
/* Port sequence: global, inout, input, output and clock ports, */
|
||||
size_t port_cnt = 0;
|
||||
for (const auto& kv : port_type2type_map) {
|
||||
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 << "," << std::endl;
|
||||
/* Print port */
|
||||
fp << "//----- " << module_manager.module_port_type_str(kv.first) << " -----" << std::endl;
|
||||
fp << generate_verilog_port(kv.second, port);
|
||||
fp << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output any port that is registered */
|
||||
fp << "//----- Registered ports -----" << std::endl;
|
||||
for (const auto& kv : port_type2type_map) {
|
||||
for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) {
|
||||
/* Skip the ports that are not registered */
|
||||
ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name());
|
||||
VTR_ASSERT(ModulePortId::INVALID() != port_id);
|
||||
if (false == module_manager.port_is_register(module_id, port_id)) {
|
||||
continue;
|
||||
}
|
||||
/* Print port */
|
||||
fp << "\t//----- " << module_manager.module_port_type_str(kv.first) << " -----" << std::endl;
|
||||
fp << "\t" << generate_verilog_port(kv.second, port);
|
||||
port_cnt++;
|
||||
fp << generate_verilog_port(VERILOG_PORT_REG, port);
|
||||
fp << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Print a Verilog module declaration (definition + port list
|
||||
* We use the following format:
|
||||
* module <module_name> (<ports without directions>);
|
||||
* <tab><port definition with direction>
|
||||
***********************************************/
|
||||
void print_verilog_module_declaration(std::fstream& fp,
|
||||
const ModuleManager& module_manager, const ModuleId& module_id) {
|
||||
check_file_handler(fp);
|
||||
|
||||
print_verilog_module_definition(fp, module_manager.module_name(module_id));
|
||||
print_verilog_module_definition(fp, module_manager, module_id);
|
||||
|
||||
print_verilog_module_ports(fp, module_manager, module_id);
|
||||
|
||||
fp << std::endl << ");" << std::endl;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
|
@ -404,6 +448,35 @@ std::string generate_verilog_local_wire(const BasicPort& output_port,
|
|||
return wire_str;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate a string for a constant value in Verilog format:
|
||||
* <#.of bits>'b<binary numbers>
|
||||
*******************************************************************/
|
||||
std::string generate_verilog_constant_values(const std::vector<size_t>& const_values) {
|
||||
std::string str = std::to_string(const_values.size());
|
||||
str += "'b";
|
||||
for (const auto& val : const_values) {
|
||||
str += std::to_string(val);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate a verilog port with a deposite of constant values
|
||||
********************************************************************/
|
||||
std::string generate_verilog_port_constant_values(const BasicPort& output_port,
|
||||
const std::vector<size_t>& const_values) {
|
||||
std::string port_str;
|
||||
|
||||
/* Must check: the port width matches */
|
||||
VTR_ASSERT( const_values.size() == output_port.get_width() );
|
||||
|
||||
port_str = generate_verilog_port(VERILOG_PORT_CONKT, output_port);
|
||||
port_str += " = ";
|
||||
port_str += generate_verilog_constant_values(const_values);
|
||||
return port_str;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate a wire connection, that assigns constant values to a
|
||||
* Verilog port
|
||||
|
@ -414,17 +487,9 @@ void print_verilog_wire_constant_values(std::fstream& fp,
|
|||
/* Make sure we have a valid file handler*/
|
||||
check_file_handler(fp);
|
||||
|
||||
/* Must check: the port width matches */
|
||||
VTR_ASSERT( const_values.size() == output_port.get_width() );
|
||||
|
||||
fp << "\t";
|
||||
fp << "assign ";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, output_port);
|
||||
fp << " = ";
|
||||
fp << const_values.size() << "'b";
|
||||
for (const auto& val : const_values) {
|
||||
fp << val;
|
||||
}
|
||||
fp << generate_verilog_port_constant_values(output_port, const_values);
|
||||
fp << ";" << std::endl;
|
||||
}
|
||||
|
||||
|
@ -434,7 +499,8 @@ void print_verilog_wire_constant_values(std::fstream& fp,
|
|||
*******************************************************************/
|
||||
void print_verilog_wire_connection(std::fstream& fp,
|
||||
const BasicPort& output_port,
|
||||
const BasicPort& input_port) {
|
||||
const BasicPort& input_port,
|
||||
const bool& inverted) {
|
||||
/* Make sure we have a valid file handler*/
|
||||
check_file_handler(fp);
|
||||
|
||||
|
@ -445,6 +511,11 @@ void print_verilog_wire_connection(std::fstream& fp,
|
|||
fp << "assign ";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, output_port);
|
||||
fp << " = ";
|
||||
|
||||
if (true == inverted) {
|
||||
fp << "~";
|
||||
}
|
||||
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port);
|
||||
fp << ";" << std::endl;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
#include "device_port.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
/* Tips: for naming your function in this header/source file
|
||||
* If a function outputs to a file, its name should begin with "print_verilog"
|
||||
* If a function creates a string without outputting to a file, its name should begin with "generate_verilog"
|
||||
* Please show respect to this naming convention, in order to keep a clean header/source file
|
||||
* as well maintain a easy way to identify the functions
|
||||
*/
|
||||
|
||||
void print_verilog_file_header(std::fstream& fp,
|
||||
const std::string& usage);
|
||||
|
||||
|
@ -20,7 +27,7 @@ void print_verilog_comment(std::fstream& fp,
|
|||
const std::string& comment);
|
||||
|
||||
void print_verilog_module_definition(std::fstream& fp,
|
||||
const std::string& module_name);
|
||||
const ModuleManager& module_manager, const ModuleId& module_id);
|
||||
|
||||
void print_verilog_module_ports(std::fstream& fp,
|
||||
const ModuleManager& module_manager, const ModuleId& module_id);
|
||||
|
@ -50,13 +57,19 @@ BasicPort generate_verilog_bus_port(const std::vector<BasicPort>& input_ports,
|
|||
std::string generate_verilog_local_wire(const BasicPort& output_port,
|
||||
const std::vector<BasicPort>& input_ports);
|
||||
|
||||
std::string generate_verilog_constant_values(const std::vector<size_t>& const_values);
|
||||
|
||||
std::string generate_verilog_port_constant_values(const BasicPort& output_port,
|
||||
const std::vector<size_t>& const_values);
|
||||
|
||||
void print_verilog_wire_constant_values(std::fstream& fp,
|
||||
const BasicPort& output_port,
|
||||
const std::vector<size_t>& const_values);
|
||||
|
||||
void print_verilog_wire_connection(std::fstream& fp,
|
||||
const BasicPort& output_port,
|
||||
const BasicPort& input_port);
|
||||
const BasicPort& input_port,
|
||||
const bool& inverted);
|
||||
|
||||
void print_verilog_buffer_instance(std::fstream& fp,
|
||||
ModuleManager& module_manager,
|
||||
|
|
Loading…
Reference in New Issue