complete refacotriing the inv and buf part in submodules
This commit is contained in:
parent
a40e5c91ca
commit
9c43b1b753
|
@ -17,11 +17,11 @@ Inverters and Buffers
|
||||||
|
|
||||||
* design_technology:
|
* design_technology:
|
||||||
|
|
||||||
* **topology:** [inverter|buffer]. Specify the type of this component, can be either an inverter or a buffer.
|
* **topology:** [``inverter`` | ``buffer``]. Specify the type of this component, can be either an inverter or a buffer.
|
||||||
|
|
||||||
* **size:** Specify the driving strength of inverter/buffer. For a buffer, the size is the driving strength of the inverter at the second level. We consider a two-level structure for a buffer here. The support for multi-level structure of a buffer will be introduced in the tapered options.
|
* **size:** Specify the driving strength of inverter/buffer. For a buffer, the size is the driving strength of the inverter at the second level. We consider a two-level structure for a buffer here. The support for multi-level structure of a buffer will be introduced in the tapered options.
|
||||||
|
|
||||||
* **tapered:** [on|off]. Define if the buffer is a tapered (multi-level) buffer. *If "on" the following parameter are required.*
|
* **tapered:** [``on`` | ``off``]. Define if the buffer is a tapered (multi-level) buffer. *If ``on`` the following parameter are required.*
|
||||||
|
|
||||||
* **tap_drive_level:** Define the number of levels of a tapered buffer. This parameter is valid only when tapered is turned on.
|
* **tap_drive_level:** Define the number of levels of a tapered buffer. This parameter is valid only when tapered is turned on.
|
||||||
|
|
||||||
|
@ -54,6 +54,21 @@ This example shows:
|
||||||
* Size of 1 for the output strength
|
* Size of 1 for the output strength
|
||||||
* The tapered parameter is not declared and is off by default
|
* The tapered parameter is not declared and is off by default
|
||||||
|
|
||||||
|
**Power-gated Inverter x1 example**
|
||||||
|
|
||||||
|
The XML code describing an inverter which can be power-gated by the control signals ``EN`` and ``ENB`` :
|
||||||
|
|
||||||
|
.. code-block:: xml
|
||||||
|
|
||||||
|
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1">
|
||||||
|
<design_technology type="cmos" topology="inverter" size="3" tapered="off" power_gated="true"/>
|
||||||
|
<port type="input" prefix="in" size="1" lib_name="I"/>
|
||||||
|
<port type="input" prefix="EN" size="1" lib_name="EN" is_global="true" default_val="0" is_config_enable="true"/>
|
||||||
|
<port type="input" prefix="ENB" size="1" lib_name="ENB" is_global="true" default_val="1" is_config_enable="true"/>
|
||||||
|
<port type="output" prefix="out" size="1" lib_name="Z"/>
|
||||||
|
</circuit_model>
|
||||||
|
|
||||||
|
.. note:: For power-gated inverters: all the control signals must be set as ``config_enable`` so that the testbench generation will generate testing waveforms. If the power-gated inverters are auto-generated , all the ``config_enable`` signals must be ``global`` signals as well. If the pwoer-gated inverters come from user-defined netlists, restrictions on ``global`` signals are free.
|
||||||
|
|
||||||
**Buffer x2 example**
|
**Buffer x2 example**
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,13 @@ Define circuit_models
|
||||||
|
|
||||||
* **circuit_model**: the child node defining transistor-level modeling parameters.
|
* **circuit_model**: the child node defining transistor-level modeling parameters.
|
||||||
|
|
||||||
* **type**: can be [ inv_buf | pass_gate | mux | wire | chan_wire | sram | lut | ff | scff | hard_logic | iopad ]. Specify the type of circuit model. The provided types cover all the modules in FPGAs. For the circuit models in the type of mux/wire/chan_wire/lut, FPGA-Verilog/SPICE can auto-generate Verilog/SPICE netlists. For the rest, FPGA-Verilog/SPICE requires a user-defined Verilog/SPICE netlist.
|
* **type**: can be [ ``inv_buf`` | ``pass_gate`` | ``gate`` | ``mux`` | ``wire`` | ``chan_wire`` | ``sram`` | ``lut`` | ``ff`` | ``scff`` | ``hard_logic`` | ``iopad`` ]. Specify the type of circuit model. The provided types cover all the modules in FPGAs. For the circuit models in the type of mux/wire/chan_wire/lut, FPGA-Verilog/SPICE can auto-generate Verilog/SPICE netlists. For the rest, FPGA-Verilog/SPICE requires a user-defined Verilog/SPICE netlist.
|
||||||
|
|
||||||
* **name**: define the name of this circuit model. The name should be unique and will be used to create the sub-circuit of the circuit model in Verilog/SPICE netlists. Note that for a customized Verilog/SPICE netlist, the name defined here should be the name of the top-level sub-circuit in the customized Verilog/SPICE netlist. FPGA-Verilog/SPICE will check if the given name is conflicted with any reserved words.
|
* **name**: define the name of this circuit model. The name should be unique and will be used to create the sub-circuit of the circuit model in Verilog/SPICE netlists. Note that for a customized Verilog/SPICE netlist, the name defined here should be the name of the top-level sub-circuit in the customized Verilog/SPICE netlist. FPGA-Verilog/SPICE will check if the given name is conflicted with any reserved words.
|
||||||
|
|
||||||
* **prefix**: specify the name of the circuit_model to shown in the auto-generated Verilog/SPICE netlists. The prefix can be the same as the name defined above. And again, the prefix should be unique.
|
* **prefix**: specify the name of the circuit_model to shown in the auto-generated Verilog/SPICE netlists. The prefix can be the same as the name defined above. And again, the prefix should be unique.
|
||||||
|
|
||||||
* **is_default**: can be [1|0], corresponding to [true|false] respectively. Specify this circuit model is the default one for some modules, such as multiplexers. If a module is not linked to any spice model by users, FPGA-Verilog/SPICE will find the default spice model defined in the same type and link. For a spice model type, only one spice model can be set as default.
|
* **is_default**: can be [``1`` | ``0``], corresponding to [true|false] respectively. Specify this circuit model is the default one for some modules, such as multiplexers. If a module is not linked to any spice model by users, FPGA-Verilog/SPICE will find the default spice model defined in the same type and link. For a spice model type, only one spice model can be set as default.
|
||||||
|
|
||||||
* **spice_netlist**: specify the path and file name of a customized Verilog/SPICE netlist. For some modules such as SRAMs, FFs, inpads, and outpads, FPGA-Verilog/SPICE does not support auto-generation of the transistor-level sub-circuits because their circuit design is highly dependent on the technology nodes. These circuit designs should be specified by users. For the other modules that can be auto-generated by FPGA-Verilog/SPICE, the user can also define a custom netlist. Multiplexers cannot be user-defined.
|
* **spice_netlist**: specify the path and file name of a customized Verilog/SPICE netlist. For some modules such as SRAMs, FFs, inpads, and outpads, FPGA-Verilog/SPICE does not support auto-generation of the transistor-level sub-circuits because their circuit design is highly dependent on the technology nodes. These circuit designs should be specified by users. For the other modules that can be auto-generated by FPGA-Verilog/SPICE, the user can also define a custom netlist. Multiplexers cannot be user-defined.
|
||||||
|
|
||||||
|
@ -87,14 +87,14 @@ Transistor level
|
||||||
|
|
||||||
* **circuit_model_name:** only valid when the type of port is sram. Specify the name of the circuit model which is connected to this port.
|
* **circuit_model_name:** only valid when the type of port is sram. Specify the name of the circuit model which is connected to this port.
|
||||||
|
|
||||||
* **mode_select:** can be either true or false. Specify if this port controls the mode switching in a configurable logic block. Only valid when the type of this port is sram. (A configurable logic block can operate in different modes, which is controlled by SRAM bits.)
|
* **mode_select:** can be either ``true`` or ``false``. Specify if this port controls the mode switching in a configurable logic block. Only valid when the type of this port is sram. (A configurable logic block can operate in different modes, which is controlled by SRAM bits.)
|
||||||
|
|
||||||
* **is_global:** can be either true or false. Specify if this port is a global port, which will be routed globally. Note that when multiple global ports are defined with the same name, these global ports will be short-wired together.
|
* **is_global:** can be either ``true`` or ``false``. Specify if this port is a global port, which will be routed globally. Note that when multiple global ports are defined with the same name, these global ports will be short-wired together.
|
||||||
|
|
||||||
* **is_set:** can be either true or false. Specify if this port controls a set signal. Only valid when is_global is true. All the set ports are connected to global set voltage stimuli in testbenches.
|
* **is_set:** can be either ``true`` or ``false``. Specify if this port controls a set signal. Only valid when is_global is true. All the set ports are connected to global set voltage stimuli in testbenches.
|
||||||
|
|
||||||
* **is_reset:** can be either true or false. Specify if this port controls a reset signal. Only valid when is_global is true. All the reset ports are connected to a global reset voltage stimuli in testbenches.
|
* **is_reset:** can be either ``true`` or ``false``. Specify if this port controls a reset signal. Only valid when is_global is true. All the reset ports are connected to a global reset voltage stimuli in testbenches.
|
||||||
|
|
||||||
* **is_config_enable:** can be either true or false. Only valid when is_global is true. Specify if this port controls a configuration-enable signal. This port is only enabled during FPGA configuration, and always disabled during FPGA operation. All the config_enable ports are connected to global configuration-enable voltage stimuli in testbenches.
|
* **is_config_enable:** can be either ``true`` or ``false``. Only valid when is_global is true. Specify if this port controls a configuration-enable signal. This port is only enabled during FPGA configuration, and always disabled during FPGA operation. All the config_enable ports are connected to global configuration-enable voltage stimuli in testbenches.
|
||||||
|
|
||||||
.. note:: Different types of ``circuit_model`` have different XML syntax, with which users can highly customize their circuit topologies. See refer to examples of ``circuit_model`` for more details.
|
.. note:: Different types of ``circuit_model`` have different XML syntax, with which users can highly customize their circuit topologies. See refer to examples of ``circuit_model`` for more details.
|
||||||
|
|
|
@ -269,6 +269,24 @@ enum e_spice_model_buffer_type CircuitLibrary::buffer_type(const CircuitModelId&
|
||||||
return buffer_types_[model_id];
|
return buffer_types_[model_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the number of levels of buffer for a circuit model
|
||||||
|
* Only applicable for BUF/INV circuit model
|
||||||
|
*/
|
||||||
|
size_t CircuitLibrary::buffer_num_levels(const CircuitModelId& model_id) const {
|
||||||
|
/* validate the model_id */
|
||||||
|
VTR_ASSERT(valid_model_id(model_id));
|
||||||
|
/* validate the circuit model type is BUF */
|
||||||
|
VTR_ASSERT(SPICE_MODEL_INVBUF == model_type(model_id));
|
||||||
|
return buffer_num_levels_[model_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the number of levels of delay types for a circuit model */
|
||||||
|
size_t CircuitLibrary::num_delay_info(const CircuitModelId& model_id) const {
|
||||||
|
/* validate the model_id */
|
||||||
|
VTR_ASSERT(valid_model_id(model_id));
|
||||||
|
return delay_types_[model_id].size();
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Public Accessors : Basic data query on Circuit models' Circuit Port
|
* Public Accessors : Basic data query on Circuit models' Circuit Port
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
@ -571,6 +589,57 @@ bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const {
|
||||||
return port_is_prog_[circuit_port_id];
|
return port_is_prog_[circuit_port_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Public Accessors : Methods to visit timing graphs
|
||||||
|
***********************************************************************/
|
||||||
|
/* Find all the edges belonging to a circuit model */
|
||||||
|
std::vector<CircuitEdgeId> CircuitLibrary::timing_edges_by_model(const CircuitModelId& model_id) const {
|
||||||
|
/* Validate the model id */
|
||||||
|
VTR_ASSERT_SAFE(valid_model_id(model_id));
|
||||||
|
|
||||||
|
std::vector<CircuitEdgeId> model_edges;
|
||||||
|
for (const auto& edge : edge_ids_) {
|
||||||
|
/* Bypass edges whose parent is not the model_id */
|
||||||
|
if (model_id != edge_parent_model_ids_[edge]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Update the edge list */
|
||||||
|
model_edges.push_back(edge);
|
||||||
|
}
|
||||||
|
return model_edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get source/sink nodes and delay of edges */
|
||||||
|
CircuitPortId CircuitLibrary::timing_edge_src_port(const CircuitEdgeId& edge) const {
|
||||||
|
/* Validate the edge id */
|
||||||
|
VTR_ASSERT_SAFE(valid_edge_id(edge));
|
||||||
|
return edge_src_port_ids_[edge];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CircuitLibrary::timing_edge_src_pin(const CircuitEdgeId& edge) const {
|
||||||
|
/* Validate the edge id */
|
||||||
|
VTR_ASSERT_SAFE(valid_edge_id(edge));
|
||||||
|
return edge_src_pin_ids_[edge];
|
||||||
|
}
|
||||||
|
|
||||||
|
CircuitPortId CircuitLibrary::timing_edge_sink_port(const CircuitEdgeId& edge) const {
|
||||||
|
/* Validate the edge id */
|
||||||
|
VTR_ASSERT_SAFE(valid_edge_id(edge));
|
||||||
|
return edge_sink_port_ids_[edge];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CircuitLibrary::timing_edge_sink_pin(const CircuitEdgeId& edge) const {
|
||||||
|
/* Validate the edge id */
|
||||||
|
VTR_ASSERT_SAFE(valid_edge_id(edge));
|
||||||
|
return edge_sink_pin_ids_[edge];
|
||||||
|
}
|
||||||
|
|
||||||
|
float CircuitLibrary::timing_edge_delay(const CircuitEdgeId& edge, const enum spice_model_delay_type& delay_type) const {
|
||||||
|
/* Validate the edge id */
|
||||||
|
VTR_ASSERT_SAFE(valid_edge_id(edge));
|
||||||
|
return edge_timing_info_[edge][delay_type];
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Public Accessors : Methods to find circuit model
|
* Public Accessors : Methods to find circuit model
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
@ -1498,7 +1567,7 @@ void CircuitLibrary::build_model_timing_graph(const CircuitModelId& model_id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Add an edge to bridge the from_pin_id and to_pin_id */
|
/* Add an edge to bridge the from_pin_id and to_pin_id */
|
||||||
add_edge(from_port_id, from_pin_id, to_port_id, to_pin_id);
|
add_edge(model_id, from_port_id, from_pin_id, to_port_id, to_pin_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1540,14 +1609,19 @@ void CircuitLibrary::build_timing_graphs() {
|
||||||
* Internal mutators: build timing graphs
|
* Internal mutators: build timing graphs
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
/* Add an edge between two pins of two ports, and assign an default timing value */
|
/* Add an edge between two pins of two ports, and assign an default timing value */
|
||||||
void CircuitLibrary::add_edge(const CircuitPortId& from_port, const size_t& from_pin,
|
void CircuitLibrary::add_edge(const CircuitModelId& model_id,
|
||||||
|
const CircuitPortId& from_port, const size_t& from_pin,
|
||||||
const CircuitPortId& to_port, const size_t& to_pin) {
|
const CircuitPortId& to_port, const size_t& to_pin) {
|
||||||
|
/* validate the model_id */
|
||||||
|
VTR_ASSERT(valid_model_id(model_id));
|
||||||
|
|
||||||
/* Create an edge in the edge id list */
|
/* Create an edge in the edge id list */
|
||||||
CircuitEdgeId edge_id = CircuitEdgeId(edge_ids_.size());
|
CircuitEdgeId edge_id = CircuitEdgeId(edge_ids_.size());
|
||||||
/* Expand the edge list */
|
/* Expand the edge list */
|
||||||
edge_ids_.push_back(edge_id);
|
edge_ids_.push_back(edge_id);
|
||||||
|
|
||||||
/* Initialize other attributes */
|
/* Initialize other attributes */
|
||||||
|
edge_parent_model_ids_.push_back(model_id);
|
||||||
|
|
||||||
/* Update the list of incoming edges for to_port */
|
/* Update the list of incoming edges for to_port */
|
||||||
/* Resize upon need */
|
/* Resize upon need */
|
||||||
|
@ -1757,6 +1831,11 @@ bool CircuitLibrary::valid_circuit_pin_id(const CircuitPortId& circuit_port_id,
|
||||||
return ( size_t(pin_id) < port_size(circuit_port_id) );
|
return ( size_t(pin_id) < port_size(circuit_port_id) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CircuitLibrary::valid_edge_id(const CircuitEdgeId& edge_id) const {
|
||||||
|
/* validate the model_id */
|
||||||
|
return ( size_t(edge_id) < edge_ids_.size() ) && ( edge_id == edge_ids_[edge_id] );
|
||||||
|
}
|
||||||
|
|
||||||
bool CircuitLibrary::valid_delay_type(const CircuitModelId& model_id, const enum spice_model_delay_type& delay_type) const {
|
bool CircuitLibrary::valid_delay_type(const CircuitModelId& model_id, const enum spice_model_delay_type& delay_type) const {
|
||||||
/* validate the model_id */
|
/* validate the model_id */
|
||||||
VTR_ASSERT(valid_model_id(model_id));
|
VTR_ASSERT(valid_model_id(model_id));
|
||||||
|
|
|
@ -218,16 +218,25 @@ class CircuitLibrary {
|
||||||
bool dump_explicit_port_map(const CircuitModelId& model_id) const;
|
bool dump_explicit_port_map(const CircuitModelId& model_id) const;
|
||||||
enum e_spice_model_design_tech design_tech_type(const CircuitModelId& model_id) const;
|
enum e_spice_model_design_tech design_tech_type(const CircuitModelId& model_id) const;
|
||||||
bool is_power_gated(const CircuitModelId& model_id) const;
|
bool is_power_gated(const CircuitModelId& model_id) const;
|
||||||
|
/* General buffer information */
|
||||||
bool is_input_buffered(const CircuitModelId& model_id) const;
|
bool is_input_buffered(const CircuitModelId& model_id) const;
|
||||||
bool is_output_buffered(const CircuitModelId& model_id) const;
|
bool is_output_buffered(const CircuitModelId& model_id) const;
|
||||||
|
/* LUT-related information */
|
||||||
bool is_lut_intermediate_buffered(const CircuitModelId& model_id) const;
|
bool is_lut_intermediate_buffered(const CircuitModelId& model_id) const;
|
||||||
|
/* Pass-gate-logic information */
|
||||||
CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const;
|
CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const;
|
||||||
|
/* Multiplexer information */
|
||||||
enum e_spice_model_structure mux_structure(const CircuitModelId& model_id) const;
|
enum e_spice_model_structure mux_structure(const CircuitModelId& model_id) const;
|
||||||
size_t mux_num_levels(const CircuitModelId& model_id) const;
|
size_t mux_num_levels(const CircuitModelId& model_id) const;
|
||||||
bool mux_add_const_input(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;
|
size_t mux_const_input_value(const CircuitModelId& model_id) const;
|
||||||
|
/* Gate information */
|
||||||
enum e_spice_model_gate_type gate_type(const CircuitModelId& model_id) const;
|
enum e_spice_model_gate_type gate_type(const CircuitModelId& model_id) const;
|
||||||
|
/* Buffer information */
|
||||||
enum e_spice_model_buffer_type buffer_type(const CircuitModelId& model_id) const;
|
enum e_spice_model_buffer_type buffer_type(const CircuitModelId& model_id) const;
|
||||||
|
size_t buffer_num_levels(const CircuitModelId& model_id) const;
|
||||||
|
/* Delay information */
|
||||||
|
size_t num_delay_info(const CircuitModelId& model_id) const;
|
||||||
public: /* Public Accessors: Basic data query on cirucit models' Circuit Ports*/
|
public: /* Public Accessors: Basic data query on cirucit models' Circuit Ports*/
|
||||||
CircuitPortId model_port(const CircuitModelId& model_id, const std::string& name) const;
|
CircuitPortId model_port(const CircuitModelId& model_id, const std::string& name) const;
|
||||||
size_t num_model_ports(const CircuitModelId& model_id) const;
|
size_t num_model_ports(const CircuitModelId& model_id) const;
|
||||||
|
@ -256,6 +265,14 @@ class CircuitLibrary {
|
||||||
bool port_is_set(const CircuitPortId& circuit_port_id) const;
|
bool port_is_set(const CircuitPortId& circuit_port_id) const;
|
||||||
bool port_is_config_enable(const CircuitPortId& circuit_port_id) const;
|
bool port_is_config_enable(const CircuitPortId& circuit_port_id) const;
|
||||||
bool port_is_prog(const CircuitPortId& circuit_port_id) const;
|
bool port_is_prog(const CircuitPortId& circuit_port_id) const;
|
||||||
|
public: /* Public Accessors: Timing graph */
|
||||||
|
/* Get source/sink nodes and delay of edges */
|
||||||
|
std::vector<CircuitEdgeId> timing_edges_by_model(const CircuitModelId& model_id) const;
|
||||||
|
CircuitPortId timing_edge_src_port(const CircuitEdgeId& edge) const;
|
||||||
|
size_t timing_edge_src_pin(const CircuitEdgeId& edge) const;
|
||||||
|
CircuitPortId timing_edge_sink_port(const CircuitEdgeId& edge) const;
|
||||||
|
size_t timing_edge_sink_pin(const CircuitEdgeId& edge) const;
|
||||||
|
float timing_edge_delay(const CircuitEdgeId& edge, const enum spice_model_delay_type& delay_type) const;
|
||||||
public: /* Public Accessors: Methods to find circuit model */
|
public: /* Public Accessors: Methods to find circuit model */
|
||||||
CircuitModelId model(const char* name) const;
|
CircuitModelId model(const char* name) const;
|
||||||
CircuitModelId model(const std::string& name) const;
|
CircuitModelId model(const std::string& name) const;
|
||||||
|
@ -411,7 +428,8 @@ class CircuitLibrary {
|
||||||
void build_model_links();
|
void build_model_links();
|
||||||
void build_timing_graphs();
|
void build_timing_graphs();
|
||||||
public: /* Internal mutators: build timing graphs */
|
public: /* Internal mutators: build timing graphs */
|
||||||
void add_edge(const CircuitPortId& from_port, const size_t& from_pin,
|
void add_edge(const CircuitModelId& model_id,
|
||||||
|
const CircuitPortId& from_port, const size_t& from_pin,
|
||||||
const CircuitPortId& to_port, const size_t& to_pin);
|
const CircuitPortId& to_port, const size_t& to_pin);
|
||||||
void set_edge_delay(const CircuitModelId& model_id,
|
void set_edge_delay(const CircuitModelId& model_id,
|
||||||
const CircuitEdgeId& circuit_edge_id,
|
const CircuitEdgeId& circuit_edge_id,
|
||||||
|
@ -427,6 +445,7 @@ class CircuitLibrary {
|
||||||
bool valid_model_id(const CircuitModelId& model_id) const;
|
bool valid_model_id(const CircuitModelId& model_id) const;
|
||||||
bool valid_circuit_port_id(const CircuitPortId& circuit_port_id) const;
|
bool valid_circuit_port_id(const CircuitPortId& circuit_port_id) const;
|
||||||
bool valid_circuit_pin_id(const CircuitPortId& circuit_port_id, const size_t& pin_id) const;
|
bool valid_circuit_pin_id(const CircuitPortId& circuit_port_id, const size_t& pin_id) const;
|
||||||
|
bool valid_edge_id(const CircuitEdgeId& edge_id) const;
|
||||||
bool valid_delay_type(const CircuitModelId& model_id, const enum spice_model_delay_type& delay_type) const;
|
bool valid_delay_type(const CircuitModelId& model_id, const enum spice_model_delay_type& delay_type) const;
|
||||||
bool valid_circuit_edge_id(const CircuitEdgeId& circuit_edge_id) const;
|
bool valid_circuit_edge_id(const CircuitEdgeId& circuit_edge_id) const;
|
||||||
bool valid_mux_const_input_value(const size_t& const_input_value) const;
|
bool valid_mux_const_input_value(const size_t& const_input_value) const;
|
||||||
|
@ -497,6 +516,7 @@ class CircuitLibrary {
|
||||||
|
|
||||||
/* Timing graphs */
|
/* Timing graphs */
|
||||||
vtr::vector<CircuitEdgeId, CircuitEdgeId> edge_ids_;
|
vtr::vector<CircuitEdgeId, CircuitEdgeId> edge_ids_;
|
||||||
|
vtr::vector<CircuitEdgeId, CircuitModelId> edge_parent_model_ids_;
|
||||||
vtr::vector<CircuitPortId, vtr::vector<size_t, CircuitEdgeId>> port_in_edge_ids_;
|
vtr::vector<CircuitPortId, vtr::vector<size_t, CircuitEdgeId>> port_in_edge_ids_;
|
||||||
vtr::vector<CircuitPortId, vtr::vector<size_t, CircuitEdgeId>> port_out_edge_ids_;
|
vtr::vector<CircuitPortId, vtr::vector<size_t, CircuitEdgeId>> port_out_edge_ids_;
|
||||||
vtr::vector<CircuitEdgeId, CircuitPortId> edge_src_port_ids_;
|
vtr::vector<CircuitEdgeId, CircuitPortId> edge_src_port_ids_;
|
||||||
|
|
|
@ -13,6 +13,27 @@ BasicPort::BasicPort() {
|
||||||
msb_ = 0;
|
msb_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Quick constructor */
|
||||||
|
BasicPort::BasicPort(const char* name, const size_t& lsb, const size_t& msb) {
|
||||||
|
set_name(std::string(name));
|
||||||
|
set_width(lsb, msb);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicPort::BasicPort(const std::string& name, const size_t& lsb, const size_t& msb) {
|
||||||
|
set_name(name);
|
||||||
|
set_width(lsb, msb);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicPort::BasicPort(const char* name, const size_t& width) {
|
||||||
|
set_name(std::string(name));
|
||||||
|
set_width(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicPort::BasicPort(const std::string& name, const size_t& width) {
|
||||||
|
set_name(name);
|
||||||
|
set_width(width);
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy constructor */
|
/* Copy constructor */
|
||||||
BasicPort::BasicPort(const BasicPort& basic_port) {
|
BasicPort::BasicPort(const BasicPort& basic_port) {
|
||||||
set(basic_port);
|
set(basic_port);
|
||||||
|
@ -59,7 +80,7 @@ void BasicPort::set_name(const std::string& name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the port LSB and MSB */
|
/* set the port LSB and MSB */
|
||||||
void BasicPort::set_width(size_t width) {
|
void BasicPort::set_width(const size_t& width) {
|
||||||
if (0 == width) {
|
if (0 == width) {
|
||||||
make_invalid();
|
make_invalid();
|
||||||
return;
|
return;
|
||||||
|
@ -70,7 +91,7 @@ void BasicPort::set_width(size_t width) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the port LSB and MSB */
|
/* set the port LSB and MSB */
|
||||||
void BasicPort::set_width(size_t lsb, size_t msb) {
|
void BasicPort::set_width(const size_t& lsb, const size_t& msb) {
|
||||||
/* If lsb and msb is invalid, we make a default port */
|
/* If lsb and msb is invalid, we make a default port */
|
||||||
if (lsb > msb) {
|
if (lsb > msb) {
|
||||||
make_invalid();
|
make_invalid();
|
||||||
|
@ -81,18 +102,18 @@ void BasicPort::set_width(size_t lsb, size_t msb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicPort::set_lsb(size_t lsb) {
|
void BasicPort::set_lsb(const size_t& lsb) {
|
||||||
lsb_ = lsb;
|
lsb_ = lsb;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicPort::set_msb(size_t msb) {
|
void BasicPort::set_msb(const size_t& msb) {
|
||||||
msb_ = msb;
|
msb_ = msb;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increase the port width */
|
/* Increase the port width */
|
||||||
void BasicPort::expand(size_t width) {
|
void BasicPort::expand(const size_t& width) {
|
||||||
if (0 == width) {
|
if (0 == width) {
|
||||||
return; /* ignore zero-width port */
|
return; /* ignore zero-width port */
|
||||||
}
|
}
|
||||||
|
@ -114,7 +135,7 @@ void BasicPort::revert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rotate: increase both lsb and msb by an offset */
|
/* rotate: increase both lsb and msb by an offset */
|
||||||
bool BasicPort::rotate(size_t offset) {
|
bool BasicPort::rotate(const size_t& offset) {
|
||||||
/* If current port is invalid or offset is 0,
|
/* If current port is invalid or offset is 0,
|
||||||
* we do nothing
|
* we do nothing
|
||||||
*/
|
*/
|
||||||
|
@ -134,7 +155,7 @@ bool BasicPort::rotate(size_t offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rotate: decrease both lsb and msb by an offset */
|
/* rotate: decrease both lsb and msb by an offset */
|
||||||
bool BasicPort::counter_rotate(size_t offset) {
|
bool BasicPort::counter_rotate(const size_t& offset) {
|
||||||
/* If current port is invalid or offset is 0,
|
/* If current port is invalid or offset is 0,
|
||||||
* we do nothing
|
* we do nothing
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
class BasicPort {
|
class BasicPort {
|
||||||
public: /* Constructors */
|
public: /* Constructors */
|
||||||
BasicPort();
|
BasicPort();
|
||||||
|
BasicPort(const char* name, const size_t& lsb, const size_t& msb);
|
||||||
|
BasicPort(const char* name, const size_t& width);
|
||||||
|
BasicPort(const std::string& name, const size_t& lsb, const size_t& msb);
|
||||||
|
BasicPort(const std::string& name, const size_t& width);
|
||||||
BasicPort(const BasicPort& basic_port); /* Copy constructor */
|
BasicPort(const BasicPort& basic_port); /* Copy constructor */
|
||||||
public: /* Accessors */
|
public: /* Accessors */
|
||||||
size_t get_width() const; /* get the port width */
|
size_t get_width() const; /* get the port width */
|
||||||
|
@ -21,14 +25,14 @@ class BasicPort {
|
||||||
public: /* Mutators */
|
public: /* Mutators */
|
||||||
void set(const BasicPort& basic_port); /* copy */
|
void set(const BasicPort& basic_port); /* copy */
|
||||||
void set_name(const std::string& name); /* set the port LSB and MSB */
|
void set_name(const std::string& name); /* set the port LSB and MSB */
|
||||||
void set_width(size_t width); /* set the port LSB and MSB */
|
void set_width(const size_t& width); /* set the port LSB and MSB */
|
||||||
void set_width(size_t lsb, size_t msb); /* set the port LSB and MSB */
|
void set_width(const size_t& lsb, const size_t& msb); /* set the port LSB and MSB */
|
||||||
void set_lsb(size_t lsb);
|
void set_lsb(const size_t& lsb);
|
||||||
void set_msb(size_t msb);
|
void set_msb(const size_t& msb);
|
||||||
void expand(size_t width); /* Increase the port width */
|
void expand(const size_t& width); /* Increase the port width */
|
||||||
void revert(); /* Swap lsb and msb */
|
void revert(); /* Swap lsb and msb */
|
||||||
bool rotate(size_t offset); /* rotate */
|
bool rotate(const size_t& offset); /* rotate */
|
||||||
bool counter_rotate(size_t offset); /* counter rotate */
|
bool counter_rotate(const size_t& offset); /* counter rotate */
|
||||||
void reset(); /* Reset to initial port */
|
void reset(); /* Reset to initial port */
|
||||||
void combine(const BasicPort& port); /* Combine two ports */
|
void combine(const BasicPort& port); /* Combine two ports */
|
||||||
private: /* internal functions */
|
private: /* internal functions */
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/************************************************
|
/************************************************
|
||||||
* Header file for verilog_submodule_essential.cpp
|
* This file includes functions on
|
||||||
* Include function declaration on
|
|
||||||
* outputting Verilog netlists for essential gates
|
* outputting Verilog netlists for essential gates
|
||||||
* which are inverters, buffers, transmission-gates
|
* which are inverters, buffers, transmission-gates
|
||||||
* logic gates etc.
|
* logic gates etc.
|
||||||
|
@ -17,14 +16,17 @@
|
||||||
/* FPGA-Verilog context header files */
|
/* FPGA-Verilog context header files */
|
||||||
#include "verilog_global.h"
|
#include "verilog_global.h"
|
||||||
#include "verilog_writer_utils.h"
|
#include "verilog_writer_utils.h"
|
||||||
|
#include "verilog_submodule_utils.h"
|
||||||
#include "verilog_essential_gates.h"
|
#include "verilog_essential_gates.h"
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
* Print Verilog codes of a power-gated inverter
|
* Print Verilog body codes of a power-gated inverter
|
||||||
|
* This function does NOT generate any port map !
|
||||||
***********************************************/
|
***********************************************/
|
||||||
static
|
static
|
||||||
void print_verilog_power_gated_inv_module(std::fstream& fp,
|
void print_verilog_power_gated_invbuf_body(std::fstream& fp,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& circuit_model,
|
||||||
const CircuitPortId& input_port,
|
const CircuitPortId& input_port,
|
||||||
const CircuitPortId& output_port,
|
const CircuitPortId& output_port,
|
||||||
const std::vector<CircuitPortId>& power_gate_ports) {
|
const std::vector<CircuitPortId>& power_gate_ports) {
|
||||||
|
@ -72,7 +74,21 @@ void print_verilog_power_gated_inv_module(std::fstream& fp,
|
||||||
}
|
}
|
||||||
|
|
||||||
fp << ") begin" << std::endl;
|
fp << ") begin" << std::endl;
|
||||||
fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) << "_reg = ~" << circuit_lib.port_lib_name(input_port) << ";" << std::endl;
|
fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) << "_reg = ";
|
||||||
|
|
||||||
|
/* Branch on the type of inverter/buffer:
|
||||||
|
* 1. If this is an inverter or an tapered(multi-stage) buffer with odd number of stages,
|
||||||
|
* we invert the input to output
|
||||||
|
* 2. If this is a buffer or an tapere(multi-stage) buffer with even number of stages,
|
||||||
|
* we wire the input to output
|
||||||
|
*/
|
||||||
|
if ( (SPICE_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model))
|
||||||
|
|| ( (SPICE_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model))
|
||||||
|
&& (1 == circuit_lib.buffer_num_levels(circuit_model) % 2 ) ) ) {
|
||||||
|
fp << "~";
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << circuit_lib.port_lib_name(input_port) << ";" << std::endl;
|
||||||
fp << "\t\tend else begin" << std::endl;
|
fp << "\t\tend else begin" << std::endl;
|
||||||
fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) << "_reg = 1'bz;" << std::endl;
|
fp << "\t\t\tassign " << circuit_lib.port_lib_name(output_port) << "_reg = 1'bz;" << std::endl;
|
||||||
fp << "\t\tend" << std::endl;
|
fp << "\t\tend" << std::endl;
|
||||||
|
@ -80,6 +96,38 @@ void print_verilog_power_gated_inv_module(std::fstream& fp,
|
||||||
fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = " << circuit_lib.port_lib_name(output_port) << "_reg;" << std::endl;
|
fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = " << circuit_lib.port_lib_name(output_port) << "_reg;" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* Print Verilog body codes of a regular inverter
|
||||||
|
* This function does NOT generate any port map !
|
||||||
|
***********************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_invbuf_body(std::fstream& fp,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& circuit_model,
|
||||||
|
const CircuitPortId& input_port,
|
||||||
|
const CircuitPortId& output_port) {
|
||||||
|
/* Ensure a valid file handler*/
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
fp << "//----- Verilog codes of a regular inverter -----" << std::endl;
|
||||||
|
|
||||||
|
fp << "\tassign " << circuit_lib.port_lib_name(output_port) << " = (" << circuit_lib.port_lib_name(input_port) << " == 1'bz)? $random : ";
|
||||||
|
|
||||||
|
/* Branch on the type of inverter/buffer:
|
||||||
|
* 1. If this is an inverter or an tapered(multi-stage) buffer with odd number of stages,
|
||||||
|
* we invert the input to output
|
||||||
|
* 2. If this is a buffer or an tapere(multi-stage) buffer with even number of stages,
|
||||||
|
* we wire the input to output
|
||||||
|
*/
|
||||||
|
if ( (SPICE_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model))
|
||||||
|
|| ( (SPICE_MODEL_BUF_INV == circuit_lib.buffer_type(circuit_model))
|
||||||
|
&& (1 == circuit_lib.buffer_num_levels(circuit_model) % 2 ) ) ) {
|
||||||
|
fp << "~";
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << circuit_lib.port_lib_name(input_port) << ";" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
* Print a Verilog module of inverter or buffer
|
* Print a Verilog module of inverter or buffer
|
||||||
* or tapered buffer to a file
|
* or tapered buffer to a file
|
||||||
|
@ -158,107 +206,32 @@ void print_verilog_invbuf_module(std::fstream& fp,
|
||||||
/* Finish dumping ports */
|
/* Finish dumping ports */
|
||||||
|
|
||||||
/* Assign logics : depending on topology */
|
/* Assign logics : depending on topology */
|
||||||
switch (circuit_lib.buffer_type(circuit_model)) {
|
/* Error out for unsupported technology */
|
||||||
case SPICE_MODEL_BUF_INV:
|
if ( ( SPICE_MODEL_BUF_INV != circuit_lib.buffer_type(circuit_model))
|
||||||
if (TRUE == circuit_lib.is_power_gated(circuit_model)) {
|
&& ( SPICE_MODEL_BUF_BUF != circuit_lib.buffer_type(circuit_model)) ) {
|
||||||
print_verilog_power_gated_inv_module(fp, circuit_lib, input_ports[0], output_ports[0], global_ports);
|
|
||||||
}
|
|
||||||
// } else {
|
|
||||||
// fprintf(fp, "assign %s = (%s === 1'bz)? $random : ~%s;\n",
|
|
||||||
// output_port[0]->lib_name,
|
|
||||||
// input_port[0]->lib_name,
|
|
||||||
// input_port[0]->lib_name);
|
|
||||||
// }
|
|
||||||
break;
|
|
||||||
case SPICE_MODEL_BUF_BUF:
|
|
||||||
// if (TRUE == invbuf_spice_model->design_tech_info.power_gated) {
|
|
||||||
// /* Create a sensitive list */
|
|
||||||
// fprintf(fp, "reg %s_reg;\n", output_port[0]->lib_name);
|
|
||||||
// fprintf(fp, "always @(");
|
|
||||||
// /* Power-gate port first*/
|
|
||||||
// for (iport = 0; iport < num_powergate_port; iport++) {
|
|
||||||
// fprintf(fp, "%s,", powergate_port[iport]->lib_name);
|
|
||||||
// }
|
|
||||||
// fprintf(fp, "%s) begin\n",
|
|
||||||
// input_port[0]->lib_name);
|
|
||||||
// /* Dump the case of power-gated */
|
|
||||||
// fprintf(fp, " if (");
|
|
||||||
// port_cnt = 0; /* Initialize the counter: decide if we need to put down '&&' */
|
|
||||||
// for (iport = 0; iport < num_powergate_port; iport++) {
|
|
||||||
// if (0 == powergate_port[iport]->default_val) {
|
|
||||||
// for (ipin = 0; ipin < powergate_port[iport]->size; ipin++) {
|
|
||||||
// if ( 0 < port_cnt ) {
|
|
||||||
// fprintf(fp, "\n\t&&");
|
|
||||||
// }
|
|
||||||
// /* Power-gated signal are disable during operating, enabled during configuration,
|
|
||||||
// * Therefore, we need to reverse them here
|
|
||||||
// */
|
|
||||||
// fprintf(fp, "(~%s[%d])",
|
|
||||||
// powergate_port[iport]->lib_name,
|
|
||||||
// ipin);
|
|
||||||
// port_cnt++; /* Update port counter*/
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// assert (1 == powergate_port[iport]->default_val);
|
|
||||||
// for (ipin = 0; ipin < powergate_port[iport]->size; ipin++) {
|
|
||||||
// if ( 0 < port_cnt ) {
|
|
||||||
// fprintf(fp, "\n\t&&");
|
|
||||||
// }
|
|
||||||
// /* Power-gated signal are disable during operating, enabled during configuration,
|
|
||||||
// * Therefore, we need to reverse them here
|
|
||||||
// */
|
|
||||||
// fprintf(fp, "(%s[%d])",
|
|
||||||
// powergate_port[iport]->lib_name,
|
|
||||||
// ipin);
|
|
||||||
// port_cnt++; /* Update port counter*/
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// fprintf(fp, ") begin\n");
|
|
||||||
// fprintf(fp, "\t\tassign %s_reg = %s;\n",
|
|
||||||
// output_port[0]->lib_name,
|
|
||||||
// input_port[0]->lib_name);
|
|
||||||
// fprintf(fp, "\tend else begin\n");
|
|
||||||
// fprintf(fp, "\t\tassign %s_reg = 1'bz;\n",
|
|
||||||
// output_port[0]->lib_name);
|
|
||||||
// fprintf(fp, "\tend\n");
|
|
||||||
// fprintf(fp, "end\n");
|
|
||||||
// fprintf(fp, "assign %s = %s_reg;\n",
|
|
||||||
// output_port[0]->lib_name,
|
|
||||||
// output_port[0]->lib_name);
|
|
||||||
//
|
|
||||||
// } else if (FALSE == invbuf_spice_model->design_tech_info.buffer_info->tapered_buf) {
|
|
||||||
// fprintf(fp, "assign %s = (%s === 1'bz)? $random : %s;\n",
|
|
||||||
// output_port[0]->lib_name,
|
|
||||||
// input_port[0]->lib_name,
|
|
||||||
// input_port[0]->lib_name);
|
|
||||||
// } else {
|
|
||||||
// assert (TRUE == invbuf_spice_model->design_tech_info.buffer_info->tapered_buf);
|
|
||||||
// fprintf(fp, "assign %s = (%s === 1'bz)? $random : ",
|
|
||||||
// output_port[0]->lib_name,
|
|
||||||
// input_port[0]->lib_name);
|
|
||||||
// /* depend on the stage, we may invert the output */
|
|
||||||
// if (1 == invbuf_spice_model->design_tech_info.buffer_info->tap_buf_level % 2) {
|
|
||||||
// fprintf(fp, "~");
|
|
||||||
// }
|
|
||||||
// fprintf(fp, "%s;\n",
|
|
||||||
// input_port[0]->lib_name);
|
|
||||||
// }
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
"(File:%s,[LINE%d])Invalid topology for circuit model (name=%s)!\n",
|
"(File:%s,[LINE%d])Invalid topology for circuit model (name=%s)!\n",
|
||||||
__FILE__, __LINE__, circuit_lib.model_name(circuit_model));
|
__FILE__, __LINE__, circuit_lib.model_name(circuit_model));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// /* Print timing info */
|
if (TRUE == circuit_lib.is_power_gated(circuit_model)) {
|
||||||
// dump_verilog_submodule_timing(fp, invbuf_spice_model);
|
/* Output Verilog codes for a power-gated inverter */
|
||||||
//
|
print_verilog_power_gated_invbuf_body(fp, circuit_lib, circuit_model, input_ports[0], output_ports[0], global_ports);
|
||||||
// dump_verilog_submodule_signal_init(fp, invbuf_spice_model);
|
} else {
|
||||||
|
/* Output Verilog codes for a regular inverter */
|
||||||
|
print_verilog_invbuf_body(fp, circuit_lib, circuit_model, input_ports[0], output_ports[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print timing info */
|
||||||
|
print_verilog_submodule_timing(fp, circuit_lib, circuit_model);
|
||||||
|
|
||||||
|
print_verilog_submodule_signal_init(fp, circuit_lib, circuit_model);
|
||||||
|
|
||||||
fp << "endmodule" << std::endl << std::endl;
|
fp << "endmodule" << std::endl << std::endl;
|
||||||
|
|
||||||
|
fp << "//----- END Verilog module for " << circuit_lib.model_name(circuit_model) << " -----" << std::endl;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,32 +75,20 @@ void generate_verilog_cmos_mux_branch_module_structural(std::fstream& fp,
|
||||||
fp << "module " << module_name << "(" << std::endl;
|
fp << "module " << module_name << "(" << std::endl;
|
||||||
|
|
||||||
/* Create port information */
|
/* Create port information */
|
||||||
BasicPort input_port;
|
|
||||||
/* Configure each input port */
|
/* Configure each input port */
|
||||||
input_port.set_name(std::string("in"));
|
BasicPort input_port("in", num_inputs);
|
||||||
input_port.set_width(num_inputs);
|
|
||||||
|
|
||||||
BasicPort output_port;
|
/* Configure each output port */
|
||||||
/* Configure each input port */
|
BasicPort output_port("out", num_outputs);
|
||||||
output_port.set_name(std::string("out"));
|
|
||||||
output_port.set_width(num_outputs);
|
|
||||||
|
|
||||||
BasicPort mem_port;
|
/* Configure each memory port */
|
||||||
/* Configure each input port */
|
BasicPort mem_port("mem", num_mems);
|
||||||
mem_port.set_name(std::string("mem"));
|
BasicPort mem_inv_port("mem_inv", num_mems);
|
||||||
mem_port.set_width(num_mems);
|
|
||||||
|
|
||||||
BasicPort mem_inv_port;
|
|
||||||
/* Configure each input port */
|
|
||||||
mem_inv_port.set_name(std::string("mem_inv"));
|
|
||||||
mem_inv_port.set_width(num_mems);
|
|
||||||
|
|
||||||
/* TODO: Generate global ports */
|
/* TODO: Generate global ports */
|
||||||
for (const auto& port : tgate_global_ports) {
|
for (const auto& port : tgate_global_ports) {
|
||||||
BasicPort basic_port;
|
/* Configure each global port */
|
||||||
/* Configure each input port */
|
BasicPort basic_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||||
basic_port.set_name(circuit_lib.port_prefix(port));
|
|
||||||
basic_port.set_width(circuit_lib.port_size(port));
|
|
||||||
/* Print port */
|
/* Print port */
|
||||||
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl;
|
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/************************************************
|
||||||
|
* This file includes most utilized functions for
|
||||||
|
* generating Verilog sub-modules
|
||||||
|
* such as timing matrix and signal initialization
|
||||||
|
***********************************************/
|
||||||
|
#include <fstream>
|
||||||
|
#include <limits>
|
||||||
|
#include <iomanip>
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
|
||||||
|
/* Device-level header files */
|
||||||
|
#include "spice_types.h"
|
||||||
|
#include "device_port.h"
|
||||||
|
|
||||||
|
/* FPGA-X2P context header files */
|
||||||
|
#include "fpga_x2p_utils.h"
|
||||||
|
|
||||||
|
/* FPGA-Verilog context header files */
|
||||||
|
#include "verilog_global.h"
|
||||||
|
#include "verilog_writer_utils.h"
|
||||||
|
#include "verilog_submodule_utils.h"
|
||||||
|
|
||||||
|
/* All values are printed with this precision value. The higher the
|
||||||
|
* value, the more accurate timing assignment is. Using numeric_limits
|
||||||
|
* max_digits10 guarentees that no values change during a sequence of
|
||||||
|
* float -> string -> float conversions */
|
||||||
|
constexpr int FLOAT_PRECISION = std::numeric_limits<float>::max_digits10;
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* Print a timing matrix defined in theecircuit model
|
||||||
|
* into a Verilog format.
|
||||||
|
* This function print all the timing edges available
|
||||||
|
* in the circuit model (any pin-to-pin delay)
|
||||||
|
***********************************************/
|
||||||
|
void print_verilog_submodule_timing(std::fstream& fp,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& circuit_model) {
|
||||||
|
/* return if there is no delay info */
|
||||||
|
if ( 0 == circuit_lib.num_delay_info(circuit_model)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return if there is no ports */
|
||||||
|
if (0 == circuit_lib.num_model_ports(circuit_model)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure a valid file handler*/
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
fp << std::endl;
|
||||||
|
fp << "`ifdef " << verilog_timing_preproc_flag << std::endl;
|
||||||
|
fp << "//------ BEGIN Pin-to-pin Timing constraints -----" << std::endl;
|
||||||
|
fp << "\tspecify" << std::endl;
|
||||||
|
|
||||||
|
/* Read out pin-to-pin delays by finding out all the edges belonging to a circuit model */
|
||||||
|
for (const auto& timing_edge : circuit_lib.timing_edges_by_model(circuit_model)) {
|
||||||
|
CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge);
|
||||||
|
size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge);
|
||||||
|
BasicPort src_port_info(circuit_lib.port_lib_name(src_port), src_pin, src_pin);
|
||||||
|
|
||||||
|
CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge);
|
||||||
|
size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge);
|
||||||
|
BasicPort sink_port_info(circuit_lib.port_lib_name(sink_port), sink_pin, sink_pin);
|
||||||
|
|
||||||
|
fp << "\t\t";
|
||||||
|
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, src_port_info);
|
||||||
|
fp << " => ";
|
||||||
|
fp << generate_verilog_port(VERILOG_PORT_CONKT, sink_port_info) << ")";
|
||||||
|
fp << " = ";
|
||||||
|
fp << "(" << std::setprecision(FLOAT_PRECISION) << circuit_lib.timing_edge_delay(timing_edge, SPICE_MODEL_DELAY_RISE);
|
||||||
|
fp << " => ";
|
||||||
|
fp << std::setprecision(FLOAT_PRECISION) << circuit_lib.timing_edge_delay(timing_edge, SPICE_MODEL_DELAY_RISE) << ")";
|
||||||
|
fp << ";" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "\tendspecify" << std::endl;
|
||||||
|
fp << "//------ END Pin-to-pin Timing constraints -----" << std::endl;
|
||||||
|
fp << "`endif" << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_verilog_submodule_signal_init(std::fstream& fp,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& circuit_model) {
|
||||||
|
/* Ensure a valid file handler*/
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
fp << std::endl;
|
||||||
|
fp << "`ifdef " << verilog_signal_init_preproc_flag << std::endl;
|
||||||
|
fp << "//------ BEGIN driver initialization -----" << std::endl;
|
||||||
|
fp << "\tinitial begin" << std::endl;
|
||||||
|
fp << "\t`ifdef " << verilog_formal_verification_preproc_flag << std::endl;
|
||||||
|
|
||||||
|
/* Only for formal verification: deposite a zero signal values */
|
||||||
|
/* Initialize each input port */
|
||||||
|
for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) {
|
||||||
|
fp << "\t\t$deposit(" << circuit_lib.port_lib_name(input_port) << ", 1'b0);" << std::endl;
|
||||||
|
}
|
||||||
|
fp << "\t`else" << std::endl;
|
||||||
|
|
||||||
|
/* Regular case: deposite initial signal values: a random value */
|
||||||
|
for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) {
|
||||||
|
fp << "\t\t$deposit(" << circuit_lib.port_lib_name(input_port) << ", $random);" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "\t`endif\n" << std::endl;
|
||||||
|
fp << "\tend" << std::endl;
|
||||||
|
fp << "//------ END driver initialization -----" << std::endl;
|
||||||
|
fp << "`endif" << std::endl;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/************************************************
|
||||||
|
* Header file for verilog_submodule_utils.cpp
|
||||||
|
* Include function declaration on
|
||||||
|
* most utilized functions for Verilog modules
|
||||||
|
* such as timing matrix and signal initialization
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
|
#ifndef VERILOG_SUBMODULE_UTILS_H
|
||||||
|
#define VERILOG_SUBMODULE_UTILS_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
void print_verilog_submodule_timing(std::fstream& fp,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& circuit_model);
|
||||||
|
|
||||||
|
void print_verilog_submodule_signal_init(std::fstream& fp,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& circuit_model);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue