Merge pull request #70 from LNIS-Projects/dev

Misc Updates
This commit is contained in:
Laboratory for Nano Integrated Systems (LNIS) 2020-07-24 14:45:01 -06:00 committed by GitHub
commit c1da9e3ef1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 684 additions and 100 deletions

View File

@ -75,6 +75,9 @@ python3 openfpga_flow/scripts/run_fpga_task.py fabric_key/generate_vanilla_key -
python3 openfpga_flow/scripts/run_fpga_task.py fabric_key/generate_random_key --debug --show_thread_logs
python3 openfpga_flow/scripts/run_fpga_task.py fabric_key/load_external_key --debug --show_thread_logs
echo -e "Testing Power-gating designs";
python3 openfpga_flow/scripts/run_fpga_task.py power_gated_design/power_gated_inverter --show_thread_logs --debug
# Verify MCNC big20 benchmark suite with ModelSim
# Please make sure you have ModelSim installed in the environment
# Otherwise, it will fail

View File

@ -302,7 +302,9 @@ size_t check_sram_circuit_model_ports(const CircuitLibrary& circuit_lib,
return num_err;
}
/* Check all the ports make sure, they satisfy the restriction */
/************************************************************************
* Check all the ports make sure, they satisfy the restriction
***********************************************************************/
static
size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
@ -435,6 +437,94 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
return num_err;
}
/************************************************************************
* Check the port requirements for a power-gated circuit model
* - It must have at least 2 global ports and which are config enable signals
* - It must have an Enable port which control power gating
* - It must have an EnableB port which control power gating
***********************************************************************/
static
int check_power_gated_circuit_model(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
int num_err = 0;
std::vector<CircuitPortId> global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true);
/* If the circuit model is power-gated, we need to find at least one global config_enable signals */
VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model));
/* Check all the ports we have are good for a power-gated circuit model */
/* We need at least one global port */
if (2 > global_ports.size()) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Expect at least two global ports (a pair of EN/Enb) for circuit model '%s' which is power-gated!\n",
circuit_lib.model_name(circuit_model).c_str());
num_err++;
}
/* All the global ports should be config_enable */
int num_config_enable_ports = 0;
for (const auto& port : global_ports) {
if (true == circuit_lib.port_is_config_enable(port)) {
num_config_enable_ports++;
}
}
if (2 != num_config_enable_ports) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Circuit model '%s' is power-gated. Two config-enable global ports are required!\n",
circuit_lib.model_name(circuit_model).c_str());
num_err++;
}
/* Report errors if there are any */
if (0 < num_err) {
return num_err;
}
/* Try to find a pair of Enable and ENb ports from the global ports */
CircuitPortId en_port = CircuitPortId::INVALID();
CircuitPortId enb_port = CircuitPortId::INVALID();
for (const auto& port : global_ports) {
/* Focus on config_enable ports which are power-gate control signals */
if (false == circuit_lib.port_is_config_enable(port)) {
continue;
}
if (0 == circuit_lib.port_default_value(port)) {
en_port = port;
} else {
VTR_ASSERT(1 == circuit_lib.port_default_value(port));
enb_port = port;
}
}
/* We must have valid EN/ENb ports */
if (false == circuit_lib.valid_circuit_port_id(en_port)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Fail to find an enable port for the circuit model '%s' is power-gated!\n",
circuit_lib.model_name(circuit_model).c_str());
}
if (false == circuit_lib.valid_circuit_port_id(enb_port)) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Fail to find an inverted enable port for the circuit model '%s' is power-gated!\n",
circuit_lib.model_name(circuit_model).c_str());
}
return num_err;
}
/************************************************************************
* Check the port requirements for each power-gated circuit model
***********************************************************************/
static
int check_power_gated_circuit_models(const CircuitLibrary& circuit_lib) {
int num_err = 0;
for (const CircuitModelId& circuit_model : circuit_lib.models()) {
if (true == circuit_lib.is_power_gated(circuit_model)) {
num_err += check_power_gated_circuit_model(circuit_lib, circuit_model);
}
}
return num_err;
}
/************************************************************************
* Check points to make sure we have a valid circuit library
* Detailed checkpoints:
@ -541,6 +631,9 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) {
num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_CHAN_WIRE);
num_err += check_required_default_circuit_model(circuit_lib, CIRCUIT_MODEL_WIRE);
/* 11. Check power-gated inverter/buffer models */
num_err += check_power_gated_circuit_models(circuit_lib);
/* If we have any errors, exit */
if (0 < num_err) {

View File

@ -238,7 +238,7 @@ std::string generate_routing_block_netlist_name(const std::string& prefix,
std::string generate_routing_block_netlist_name(const std::string& prefix,
const vtr::Point<size_t>& coordinate,
const std::string& postfix) {
return std::string( prefix + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + postfix );
return std::string( prefix + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") + postfix );
}
/*********************************************************************
@ -968,10 +968,8 @@ std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib,
std::string generate_logical_tile_netlist_name(const std::string& prefix,
const t_pb_graph_node* pb_graph_head,
const std::string& postfix) {
/* This must be the root node */
VTR_ASSERT(true == pb_graph_head->is_root());
/* Add the name of physical block */
std::string module_name = prefix + std::string(pb_graph_head->pb_type->name);
std::string module_name = prefix + generate_physical_block_module_name(pb_graph_head->pb_type);
module_name += postfix;
@ -1183,8 +1181,9 @@ std::string generate_grid_block_instance_name(const std::string& prefix,
module_name += generate_grid_block_netlist_name(block_name, is_block_io, io_side, std::string());
module_name += std::string("_");
module_name += std::to_string(grid_coord.x());
module_name += std::string("_");
module_name += std::string("__");
module_name += std::to_string(grid_coord.y());
module_name += std::string("_");
return module_name;
}
@ -1244,7 +1243,6 @@ std::string generate_physical_block_module_name(t_pb_type* physical_pb_type) {
return module_name;
}
/*********************************************************************
* Generate the instance name for physical block with a given index
**********************************************************************/

View File

@ -17,6 +17,8 @@
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "circuit_library_utils.h"
#include "spice_constants.h"
#include "spice_writer_utils.h"
#include "spice_essential_gates.h"
@ -112,7 +114,157 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
}
/************************************************
* Generate the SPICE subckt for an inverter
* Generate the SPICE subckt for a power gated inverter
* The Enable signal controlled the power gating
* Schematic
* LVDD
* |
* -
* ENb[0] -o||
* -
* |
* -
* ENb[1] -o||
* -
* |
* ...
* |
* -
* +-o||
* | -
* | |
* in-->+ +--> OUT
* | |
* | -
* +--||
* -
* ...
* |
* -
* EN[1] -||
* -
* |
* -
* EN[0] -||
* -
* |
* LGND
*
***********************************************/
static
int print_spice_powergated_inverter_subckt(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const TechnologyLibrary& tech_lib,
const TechnologyModelId& tech_model) {
if (false == valid_file_stream(fp)) {
return CMD_EXEC_FATAL_ERROR;
}
/* Print the inverter subckt definition */
print_spice_subckt_definition(fp, module_manager, module_id);
/* Find the input and output ports:
* we do NOT support global ports here,
* it should be handled in another type of inverter subckt (power-gated)
*/
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true);
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
/* Make sure:
* There is only 1 input port and 1 output port,
* each size of which is 1
*/
VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) );
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
/* If the circuit model is power-gated, we need to find at least one global config_enable signals */
VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model));
CircuitPortId en_port = find_circuit_model_power_gate_en_port(circuit_lib, circuit_model);
CircuitPortId enb_port = find_circuit_model_power_gate_enb_port(circuit_lib, circuit_model);
VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(en_port));
VTR_ASSERT(true == circuit_lib.valid_circuit_port_id(enb_port));
/* TODO: may consider use size/bin to compact layout etc. */
for (size_t i = 0; i < circuit_lib.buffer_size(circuit_model); ++i) {
/* Write power-gating transistor pairs using the technology model
* Note that for a mulit-bit power gating port, we should cascade the transistors
*/
bool first_enb_pin = true;
size_t last_enb_pin;
for (const auto& power_gate_pin : circuit_lib.pins(enb_port)) {
BasicPort enb_pin(circuit_lib.port_prefix(enb_port), power_gate_pin, power_gate_pin);
fp << "Xpmos_powergate_" << i << "_pin_" << power_gate_pin << " ";
/* For the first pin, we should connect it to local VDD*/
if (true == first_enb_pin) {
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << power_gate_pin << " ";
fp << generate_spice_port(enb_pin) << " ";
fp << "LVDD ";
fp << "LVDD ";
first_enb_pin = false;
} else {
VTR_ASSERT_SAFE(false == first_enb_pin);
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << last_enb_pin << " ";
fp << generate_spice_port(enb_pin) << " ";
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << power_gate_pin << " ";
fp << "LVDD ";
}
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
/* Cache the last pin*/
last_enb_pin = power_gate_pin;
}
bool first_en_pin = true;
size_t last_en_pin;
for (const auto& power_gate_pin : circuit_lib.pins(en_port)) {
BasicPort en_pin(circuit_lib.port_prefix(en_port), power_gate_pin, power_gate_pin);
fp << "Xnmos_powergate_" << i << "_pin_" << power_gate_pin << " ";
/* For the first pin, we should connect it to local VDD*/
if (true == first_en_pin) {
fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << power_gate_pin << " ";
fp << generate_spice_port(en_pin) << " ";
fp << "LGND ";
fp << "LGND ";
first_en_pin = false;
} else {
VTR_ASSERT_SAFE(false == first_enb_pin);
fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << last_en_pin << " ";
fp << circuit_lib.port_prefix(en_port) << " ";
fp << circuit_lib.port_prefix(output_ports[0]) << "_nmos_pg_" << power_gate_pin << " ";
fp << "LGND ";
}
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
/* Cache the last pin*/
last_enb_pin = power_gate_pin;
}
/* Write transistor pairs using the technology model */
fp << "Xpmos_" << i << " ";
fp << circuit_lib.port_prefix(output_ports[0]) << " ";
fp << circuit_lib.port_prefix(input_ports[0]) << " ";
fp << circuit_lib.port_prefix(output_ports[0]) << "_pmos_pg_" << circuit_lib.pins(enb_port).back() << " ";
fp << "LVDD ";
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_PMOS) << TRANSISTOR_WRAPPER_POSTFIX;
fp << "Xnmos_" << i << " ";
fp << circuit_lib.port_prefix(output_ports[0]) << " ";
fp << circuit_lib.port_prefix(input_ports[0]) << " ";
fp << circuit_lib.port_prefix(output_ports[0]) << " _nmos_pg_" << circuit_lib.pins(en_port).back() << " ";
fp << "LGND ";
fp << tech_lib.transistor_model_name(tech_model, TECH_LIB_TRANSISTOR_NMOS) << TRANSISTOR_WRAPPER_POSTFIX;
}
print_spice_subckt_end(fp, module_manager.module_name(module_id));
return CMD_EXEC_SUCCESS;
}
/************************************************
* Generate the SPICE subckt for a regular inverter
* Schematic
* LVDD
* |
@ -130,7 +282,7 @@ int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
*
***********************************************/
static
int print_spice_inverter_subckt(std::fstream& fp,
int print_spice_regular_inverter_subckt(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
@ -181,6 +333,35 @@ int print_spice_inverter_subckt(std::fstream& fp,
return CMD_EXEC_SUCCESS;
}
/************************************************
* Generate the SPICE subckt for an inverter
* Branch on the different circuit topologies
***********************************************/
static
int print_spice_inverter_subckt(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const TechnologyLibrary& tech_lib,
const TechnologyModelId& tech_model) {
int status = CMD_EXEC_SUCCESS;
if (true == circuit_lib.is_power_gated(circuit_model)) {
status = print_spice_powergated_inverter_subckt(fp,
module_manager, module_id,
circuit_lib, circuit_model,
tech_lib, tech_model);
} else {
VTR_ASSERT_SAFE(false == circuit_lib.is_power_gated(circuit_model));
status = print_spice_regular_inverter_subckt(fp,
module_manager, module_id,
circuit_lib, circuit_model,
tech_lib, tech_model);
}
return status;
}
/************************************************
* Generate the SPICE netlist for essential gates:
* - inverters and their templates

View File

@ -45,14 +45,15 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp,
/* Create a sensitive list */
fp << "\treg " << circuit_lib.port_prefix(output_port) << "_reg;" << std::endl;
fp << "\talways @(" << std::endl;
fp << "\talways @(";
/* Power-gate port first*/
for (const auto& power_gate_port : power_gate_ports) {
/* Skip first comma to dump*/
if (0 < &power_gate_port - &power_gate_ports[0]) {
fp << ",";
/* Only config_enable signal will be considered */
if (false == circuit_lib.port_is_config_enable(power_gate_port)) {
continue;
}
fp << circuit_lib.port_prefix(power_gate_port);
fp << ", ";
}
fp << circuit_lib.port_prefix(input_port) << ") begin" << std::endl;
@ -61,6 +62,10 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp,
/* For the first pin, we skip output comma */
size_t port_cnt = 0;
for (const auto& power_gate_port : power_gate_ports) {
/* Only config_enable signal will be considered */
if (false == circuit_lib.port_is_config_enable(power_gate_port)) {
continue;
}
for (const auto& power_gate_pin : circuit_lib.pins(power_gate_port)) {
if (0 < port_cnt) {
fp << std::endl << "\t\t&&";
@ -70,7 +75,7 @@ void print_verilog_power_gated_invbuf_body(std::fstream& fp,
/* Power-gated signal are disable during operating, enabled during configuration,
* Therefore, we need to reverse them here
*/
if (0 == circuit_lib.port_default_value(power_gate_port)) {
if (1 == circuit_lib.port_default_value(power_gate_port)) {
fp << "~";
}
@ -161,30 +166,6 @@ void print_verilog_invbuf_module(const ModuleManager& module_manager,
VTR_ASSERT( (1 == input_ports.size()) && (1 == circuit_lib.port_size(input_ports[0])) );
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
/* TODO: move the check codes to check_circuit_library.h */
/* If the circuit model is power-gated, we need to find at least one global config_enable signals */
if (true == circuit_lib.is_power_gated(circuit_model)) {
/* Check all the ports we have are good for a power-gated circuit model */
size_t num_err = 0;
/* We need at least one global port */
if (0 == global_ports.size()) {
num_err++;
}
/* All the global ports should be config_enable */
for (const auto& port : global_ports) {
if (false == circuit_lib.port_is_config_enable(port)) {
num_err++;
}
}
/* Report errors if there are any */
if (0 < num_err) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Inverter/buffer circuit model '%s' is power-gated. At least one config-enable global port is required!\n",
circuit_lib.model_name(circuit_model).c_str());
exit(1);
}
}
/* Create a Verilog Module based on the circuit model, and add to module manager */
ModuleId module_id = module_manager.find_module(circuit_lib.model_name(circuit_model));
VTR_ASSERT(true == module_manager.valid_module_id(module_id));

View File

@ -63,14 +63,12 @@ namespace openfpga {
*
*******************************************************************/
static
void print_verilog_primitive_block(std::fstream& fp,
void print_verilog_primitive_block(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const std::string& subckt_dir,
t_pb_graph_node* primitive_pb_graph_node,
const bool& use_explicit_mapping,
const bool& verbose) {
/* Ensure a valid file handler */
VTR_ASSERT(true == valid_file_stream(fp));
/* Ensure a valid pb_graph_node */
if (nullptr == primitive_pb_graph_node) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
@ -78,6 +76,24 @@ void print_verilog_primitive_block(std::fstream& fp,
exit(1);
}
/* Give a name to the Verilog netlist */
/* Create the file name for Verilog */
std::string verilog_fname(subckt_dir
+ generate_logical_tile_netlist_name(std::string(), primitive_pb_graph_node, std::string(VERILOG_NETLIST_FILE_POSTFIX))
);
VTR_LOG("Writing Verilog netlist '%s' for primitive pb_type '%s' ...",
verilog_fname.c_str(), primitive_pb_graph_node->pb_type->name);
VTR_LOGV(verbose, "\n");
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_stream(verilog_fname.c_str(), fp);
print_verilog_file_header(fp, std::string("Verilog modules for primitive pb_type: " + std::string(primitive_pb_graph_node->pb_type->name)));
/* Generate the module name for this primitive pb_graph_node*/
std::string primitive_module_name = generate_physical_block_module_name(primitive_pb_graph_node->pb_type);
@ -93,8 +109,13 @@ void print_verilog_primitive_block(std::fstream& fp,
/* Write the verilog module */
write_verilog_module_to_file(fp, module_manager, primitive_module, use_explicit_mapping);
/* Add an empty line as a splitter */
fp << std::endl;
/* Close file handler */
fp.close();
/* Add fname to the netlist name list */
NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname);
VTR_ASSERT(NetlistId::INVALID() != nlist_id);
netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST);
VTR_LOGV(verbose, "Done\n");
}
@ -115,14 +136,13 @@ void print_verilog_primitive_block(std::fstream& fp,
* to its parent in module manager
*******************************************************************/
static
void rec_print_verilog_logical_tile(std::fstream& fp,
void rec_print_verilog_logical_tile(NetlistManager& netlist_manager,
const ModuleManager& module_manager,
const VprDeviceAnnotation& device_annotation,
const std::string& subckt_dir,
t_pb_graph_node* physical_pb_graph_node,
const bool& use_explicit_mapping,
const bool& verbose) {
/* Check the file handler*/
VTR_ASSERT(true == valid_file_stream(fp));
/* Check cur_pb_graph_node*/
if (nullptr == physical_pb_graph_node) {
@ -143,8 +163,9 @@ void rec_print_verilog_logical_tile(std::fstream& fp,
if (false == is_primitive_pb_type(physical_pb_type)) {
for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) {
/* Go recursive to visit the children */
rec_print_verilog_logical_tile(fp,
rec_print_verilog_logical_tile(netlist_manager,
module_manager, device_annotation,
subckt_dir,
&(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]),
use_explicit_mapping,
verbose);
@ -156,7 +177,9 @@ void rec_print_verilog_logical_tile(std::fstream& fp,
* explict port mapping. This aims to avoid any port sequence issues!!!
*/
if (true == is_primitive_pb_type(physical_pb_type)) {
print_verilog_primitive_block(fp, module_manager,
print_verilog_primitive_block(netlist_manager,
module_manager,
subckt_dir,
physical_pb_graph_node,
true,
verbose);
@ -164,6 +187,24 @@ void rec_print_verilog_logical_tile(std::fstream& fp,
return;
}
/* Give a name to the Verilog netlist */
/* Create the file name for Verilog */
std::string verilog_fname(subckt_dir
+ generate_logical_tile_netlist_name(std::string(), physical_pb_graph_node, std::string(VERILOG_NETLIST_FILE_POSTFIX))
);
VTR_LOG("Writing Verilog netlist '%s' for pb_type '%s' ...",
verilog_fname.c_str(), physical_pb_type->name);
VTR_LOGV(verbose, "\n");
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_stream(verilog_fname.c_str(), fp);
print_verilog_file_header(fp, std::string("Verilog modules for pb_type: " + std::string(physical_pb_type->name)));
/* Generate the name of the Verilog module for this pb_type */
std::string pb_module_name = generate_physical_block_module_name(physical_pb_type);
@ -172,7 +213,7 @@ void rec_print_verilog_logical_tile(std::fstream& fp,
VTR_ASSERT(true == module_manager.valid_module_id(pb_module));
VTR_LOGV(verbose,
"Writing Verilog codes of logical tile block '%s'...",
"Writing Verilog codes of pb_type '%s'...",
module_manager.module_name(pb_module).c_str());
/* Comment lines */
@ -183,8 +224,13 @@ void rec_print_verilog_logical_tile(std::fstream& fp,
print_verilog_comment(fp, std::string("----- END Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----"));
/* Add an empty line as a splitter */
fp << std::endl;
/* Close file handler */
fp.close();
/* Add fname to the netlist name list */
NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname);
VTR_ASSERT(NetlistId::INVALID() != nlist_id);
netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST);
VTR_LOGV(verbose, "Done\n");
}
@ -201,23 +247,10 @@ void print_verilog_logical_tile_netlist(NetlistManager& netlist_manager,
t_pb_graph_node* pb_graph_head,
const bool& use_explicit_mapping,
const bool& verbose) {
/* Give a name to the Verilog netlist */
/* Create the file name for Verilog */
std::string verilog_fname(subckt_dir
+ generate_logical_tile_netlist_name(std::string(LOGICAL_MODULE_VERILOG_FILE_NAME_PREFIX), pb_graph_head, std::string(VERILOG_NETLIST_FILE_POSTFIX))
);
VTR_LOG("Writing Verilog netlist '%s' for logic tile '%s' ...",
verilog_fname.c_str(), pb_graph_head->pb_type->name);
VTR_LOGV(verbose, "\n");
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_stream(verilog_fname.c_str(), fp);
print_verilog_file_header(fp, std::string("Verilog modules for logical tile: " + std::string(pb_graph_head->pb_type->name) + "]"));
VTR_LOG("Writing Verilog netlists for logic tile '%s' ...",
pb_graph_head->pb_type->name);
VTR_LOG("\n");
/* Print Verilog modules for all the pb_types/pb_graph_nodes
* use a Depth-First Search Algorithm to print the sub-modules
@ -226,23 +259,14 @@ void print_verilog_logical_tile_netlist(NetlistManager& netlist_manager,
* to its parent in module manager
*/
/* Print Verilog modules starting from the top-level pb_type/pb_graph_node, and traverse the graph in a recursive way */
rec_print_verilog_logical_tile(fp, module_manager,
rec_print_verilog_logical_tile(netlist_manager,
module_manager,
device_annotation,
subckt_dir,
pb_graph_head,
use_explicit_mapping,
verbose);
/* Add an empty line as a splitter */
fp << std::endl;
/* Close file handler */
fp.close();
/* Add fname to the netlist name list */
NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname);
VTR_ASSERT(NetlistId::INVALID() != nlist_id);
netlist_manager.set_netlist_type(nlist_id, NetlistManager::LOGIC_BLOCK_NETLIST);
VTR_LOG("Done\n");
VTR_LOG("\n");
}
@ -270,7 +294,7 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager,
/* Give a name to the Verilog netlist */
/* Create the file name for Verilog */
std::string verilog_fname(subckt_dir
+ generate_grid_block_netlist_name(std::string(phy_block_type->name),
+ generate_grid_block_netlist_name(std::string(GRID_MODULE_NAME_PREFIX) + std::string(phy_block_type->name),
is_io_type(phy_block_type),
border_side,
std::string(VERILOG_NETLIST_FILE_POSTFIX))

View File

@ -287,4 +287,62 @@ bool check_configurable_memory_circuit_model(const e_config_protocol_type& confi
return (0 == num_err);
}
/************************************************************************
* Try to find the enable port control power-gate for a power-gated circuit model
* We will return the first port that meet the requirement:
* - a global port
* - its function is labelled as config_enable
* - default value is 0
* Return invalid id if not found
***********************************************************************/
CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model));
std::vector<CircuitPortId> global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true);
/* Try to find an ENABLE port from the global ports */
CircuitPortId en_port = CircuitPortId::INVALID();
for (const auto& port : global_ports) {
/* Focus on config_enable ports which are power-gate control signals */
if (false == circuit_lib.port_is_config_enable(port)) {
continue;
}
if (1 == circuit_lib.port_default_value(port)) {
en_port = port;
break;
}
}
return en_port;
}
/************************************************************************
* Try to find the enableB port control power-gate for a power-gated circuit model
* We will return the first port that meet the requirement:
* - a global port
* - its function is labelled as config_enable
* - default value is 1
* Return invalid id if not found
***********************************************************************/
CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
CircuitPortId enb_port = CircuitPortId::INVALID();
VTR_ASSERT(true == circuit_lib.is_power_gated(circuit_model));
std::vector<CircuitPortId> global_ports = circuit_lib.model_global_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true, true);
/* Try to find an ENABLE_B port from the global ports */
for (const auto& port : global_ports) {
/* Focus on config_enable ports which are power-gate control signals */
if (false == circuit_lib.port_is_config_enable(port)) {
continue;
}
if (0 == circuit_lib.port_default_value(port)) {
enb_port = port;
break;
}
}
return enb_port;
}
} /* end namespace openfpga */

View File

@ -43,6 +43,12 @@ bool check_configurable_memory_circuit_model(const e_config_protocol_type& confi
const CircuitLibrary& circuit_lib,
const CircuitModelId& config_mem_circuit_model);
CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
CircuitPortId find_circuit_model_power_gate_enb_port(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
} /* end namespace openfpga */
#endif

View File

@ -1,35 +1,35 @@
<fabric_key>
<key id="0" name="sb_2__2_" value="0" alias="sb_2__2_"/>
<key id="1" name="grid_clb" value="3" alias="grid_clb_2_2"/>
<key id="1" name="grid_clb" value="3" alias="grid_clb_2__2_"/>
<key id="2" name="sb_0__1_" value="0" alias="sb_0__1_"/>
<key id="3" name="cby_0__1_" value="0" alias="cby_0__1_"/>
<key id="4" name="grid_clb" value="2" alias="grid_clb_2_1"/>
<key id="5" name="grid_io_left" value="0" alias="grid_io_left_0_1"/>
<key id="4" name="grid_clb" value="2" alias="grid_clb_2__1_"/>
<key id="5" name="grid_io_left" value="0" alias="grid_io_left_0__1_"/>
<key id="6" name="sb_1__0_" value="0" alias="sb_1__0_"/>
<key id="7" name="sb_1__1_" value="0" alias="sb_1__1_"/>
<key id="8" name="cbx_1__1_" value="1" alias="cbx_2__1_"/>
<key id="9" name="cby_1__1_" value="1" alias="cby_1__2_"/>
<key id="10" name="grid_io_right" value="1" alias="grid_io_right_3_2"/>
<key id="10" name="grid_io_right" value="1" alias="grid_io_right_3__2_"/>
<key id="11" name="cbx_1__0_" value="1" alias="cbx_2__0_"/>
<key id="12" name="cby_1__1_" value="0" alias="cby_1__1_"/>
<key id="13" name="grid_io_right" value="0" alias="grid_io_right_3_1"/>
<key id="14" name="grid_io_bottom" value="0" alias="grid_io_bottom_1_0"/>
<key id="13" name="grid_io_right" value="0" alias="grid_io_right_3__1_"/>
<key id="14" name="grid_io_bottom" value="0" alias="grid_io_bottom_1__0_"/>
<key id="15" name="cby_2__1_" value="0" alias="cby_2__1_"/>
<key id="16" name="sb_2__1_" value="0" alias="sb_2__1_"/>
<key id="17" name="cbx_1__0_" value="0" alias="cbx_1__0_"/>
<key id="18" name="grid_clb" value="1" alias="grid_clb_1_2"/>
<key id="18" name="grid_clb" value="1" alias="grid_clb_1__2_"/>
<key id="19" name="cbx_1__2_" value="0" alias="cbx_1__2_"/>
<key id="20" name="cbx_1__2_" value="1" alias="cbx_2__2_"/>
<key id="21" name="sb_2__0_" value="0" alias="sb_2__0_"/>
<key id="22" name="sb_1__2_" value="0" alias="sb_1__2_"/>
<key id="23" name="cby_0__1_" value="1" alias="cby_0__2_"/>
<key id="24" name="sb_0__0_" value="0" alias="sb_0__0_"/>
<key id="25" name="grid_clb" value="0" alias="grid_clb_1_1"/>
<key id="25" name="grid_clb" value="0" alias="grid_clb_1__1_"/>
<key id="26" name="cby_2__1_" value="1" alias="cby_2__2_"/>
<key id="27" name="grid_io_top" value="1" alias="grid_io_top_2_3"/>
<key id="27" name="grid_io_top" value="1" alias="grid_io_top_2__3_"/>
<key id="28" name="sb_0__2_" value="0" alias="sb_0__2_"/>
<key id="29" name="grid_io_bottom" value="1" alias="grid_io_bottom_2_0"/>
<key id="29" name="grid_io_bottom" value="1" alias="grid_io_bottom_2__0_"/>
<key id="30" name="cbx_1__1_" value="0" alias="cbx_1__1_"/>
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1_3"/>
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0_2"/>
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1__3_"/>
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0__2_"/>
</fabric_key>

View File

@ -23,5 +23,6 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f
- stdcell: If circuit designs are built with standard cells only
- tree\_mux: If routing multiplexers are built with a tree-like structure
- <feature_size>: The technology node which the delay numbers are extracted from.
- powergate : The FPGA has power-gating techniques applied. If not defined, there is no power-gating.
Other features are used in naming should be listed here.

View File

@ -0,0 +1,206 @@
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k6_N10_40nm.xml
- General purpose logic block
- K = 6, N = 10, I = 40
- Single mode
- Routing architecture
- L = 4, fc_in = 0.15, fc_out = 0.1
-->
<openfpga_architecture>
<technology_library>
<device_library>
<device_model name="logic" type="transistor">
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="0.9" pn_ratio="2"/>
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
</device_model>
<device_model name="io" type="transistor">
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
<design vdd="2.5" pn_ratio="3"/>
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
</device_model>
</device_library>
<variation_library>
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
</variation_library>
</technology_library>
<circuit_library>
<!-- An inverter with a pair of power-gate control signals
en port: when it is '1', it is power gated
enb port: when it is '0', it is power gated
-->
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
<design_technology type="cmos" power_gated="true" topology="inverter" size="1"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="input" prefix="en" size="1" is_global="true" default_val="0" is_config_enable="true"/>
<port type="input" prefix="enb" size="1" is_global="true" default_val="1" is_config_enable="true"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
<device_technology device_model_name="logic"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in" out_port="out">
10e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in" out_port="out">
10e-12
</delay_matrix>
</circuit_model>
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="input" prefix="sel" size="1"/>
<port type="input" prefix="selb" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
10e-12 5e-12 5e-12
</delay_matrix>
</circuit_model>
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
</circuit_model>
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
<design_technology type="cmos"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<wire_param model_type="pi" R="0" C="0" num_level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
</circuit_model>
<circuit_model type="mux" name="mux_2level" prefix="mux_2level" dump_structural_verilog="true">
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_2level_tapbuf" prefix="mux_2level_tapbuf" dump_structural_verilog="true">
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<circuit_model type="mux" name="mux_1level_tapbuf" prefix="mux_1level_tapbuf" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="one_level" add_const_input="true" const_input_val="1"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="1"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="1"/>
</circuit_model>
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
<circuit_model type="ff" name="static_dff" prefix="dff" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/SpiceNetlists/ff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/VerilogNetlists/ff.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="D" size="1"/>
<port type="input" prefix="set" size="1" is_global="true" default_val="0" is_set="true"/>
<port type="input" prefix="reset" size="1" is_global="true" default_val="0" is_reset="true"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="clk" size="1" is_global="true" default_val="0" />
</circuit_model>
<circuit_model type="lut" name="lut4" prefix="lut4" dump_structural_verilog="true">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
<pass_gate_logic circuit_model_name="TGATE"/>
<port type="input" prefix="in" size="4"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="16"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="sram" name="config_latch" prefix="config_latch" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/SpiceNetlists/config_latch.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/VerilogNetlists/config_latch.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="input" prefix="pReset" lib_name="reset" size="1" is_global="true" default_val="0" is_reset="true" is_prog="true"/>
<port type="bl" prefix="bl" size="1"/>
<port type="wl" prefix="wl" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="output" prefix="Qb" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="clk" size="1" is_global="true" default_val="0" is_prog="true"/>
</circuit_model>
<circuit_model type="iopad" name="iopad" prefix="iopad" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/SpiceNetlists/io.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/VerilogNetlists/io.v">
<design_technology type="cmos"/>
<input_buffer exist="true" circuit_model_name="INVTX1"/>
<output_buffer exist="true" circuit_model_name="INVTX1"/>
<port type="inout" prefix="pad" size="1" is_global="true" is_io="true"/>
<port type="sram" prefix="en" size="1" mode_select="true" circuit_model_name="config_latch" default_val="1"/>
<port type="input" prefix="outpad" size="1"/>
<port type="output" prefix="inpad" size="1"/>
</circuit_model>
</circuit_library>
<configuration_protocol>
<organization type="frame_based" circuit_model_name="config_latch"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_2level_tapbuf"/>
</connection_block>
<switch_block>
<switch name="0" circuit_model_name="mux_2level_tapbuf"/>
</switch_block>
<routing_segment>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<pb_type_annotations>
<!-- physical pb_type binding in complex block IO -->
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
<pb_type name="io[physical].iopad" circuit_model_name="iopad" mode_bits="1"/>
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
<!-- End physical pb_type binding in complex block IO -->
<!-- physical pb_type binding in complex block CLB -->
<!-- physical mode will be the default mode if not specified -->
<pb_type name="clb">
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
<interconnect name="crossbar" circuit_model_name="mux_2level"/>
</pb_type>
<pb_type name="clb.fle[n1_lut4].ble4.lut4" circuit_model_name="lut4"/>
<pb_type name="clb.fle[n1_lut4].ble4.ff" circuit_model_name="static_dff"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -0,0 +1,33 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configuration file for running experiments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
# Each job execute fpga_flow script on combination of architecture & benchmark
# timeout_each_job is timeout for each job
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
[GENERAL]
run_engine=openfpga_shell
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/fast_configuration_example_script.openfpga
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_powergate_frame_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
external_fabric_key_file=
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
[SYNTHESIS_PARAM]
bench0_top = and2
bench0_chan_width = 300
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=