[FPGA-Verilog] Now consider clock constraints for BL/WL shift registers

This commit is contained in:
tangxifan 2021-10-06 11:39:28 -07:00
parent 95b877924a
commit 82ed6b177b
3 changed files with 116 additions and 40 deletions

View File

@ -11,6 +11,9 @@
#include "vtr_assert.h" #include "vtr_assert.h"
#include "vtr_time.h" #include "vtr_time.h"
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
/* Headers from openfpgautil library */ /* Headers from openfpgautil library */
#include "openfpga_port.h" #include "openfpga_port.h"
#include "openfpga_digest.h" #include "openfpga_digest.h"
@ -1121,15 +1124,16 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
* 1. the enable signal * 1. the enable signal
*******************************************************************/ *******************************************************************/
static static
void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp, int print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp,
const ConfigProtocol& config_protocol, const ConfigProtocol& config_protocol,
const ModuleManager& module_manager, const SimulationSetting& sim_settings,
const ModuleId& top_module, const ModuleManager& module_manager,
const bool& fast_configuration, const ModuleId& top_module,
const bool& bit_value_to_skip, const bool& fast_configuration,
const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip,
const float& prog_clock_period, const FabricBitstream& fabric_bitstream,
const float& timescale) { const float& prog_clock_period,
const float& timescale) {
/* Validate the file stream */ /* Validate the file stream */
valid_file_stream(fp); valid_file_stream(fp);
@ -1140,11 +1144,11 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f
case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_SCAN_CHAIN:
break; break;
case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_QL_MEMORY_BANK:
print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp, return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp,
config_protocol, config_protocol, sim_settings,
module_manager,top_module, module_manager, top_module,
fast_configuration, bit_value_to_skip, fabric_bitstream, fast_configuration, bit_value_to_skip, fabric_bitstream,
prog_clock_period, timescale); prog_clock_period, timescale);
break; break;
case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK:
case CONFIG_MEM_FRAME_BASED: { case CONFIG_MEM_FRAME_BASED: {
@ -1166,6 +1170,8 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f
"Invalid SRAM organization type!\n"); "Invalid SRAM organization type!\n");
exit(1); exit(1);
} }
return CMD_EXEC_SUCCESS;
} }
/******************************************************************** /********************************************************************
@ -1974,12 +1980,17 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
VERILOG_SIM_TIMESCALE); VERILOG_SIM_TIMESCALE);
/* Generate stimuli for programming interface */ /* Generate stimuli for programming interface */
print_verilog_top_testbench_configuration_protocol_stimulus(fp, int status = CMD_EXEC_SUCCESS;
config_protocol, status = print_verilog_top_testbench_configuration_protocol_stimulus(fp,
module_manager, top_module, config_protocol, simulation_parameters,
fast_configuration, bit_value_to_skip, fabric_bitstream, module_manager, top_module,
prog_clock_period, fast_configuration, bit_value_to_skip, fabric_bitstream,
VERILOG_SIM_TIMESCALE); prog_clock_period,
VERILOG_SIM_TIMESCALE);
if (status == CMD_EXEC_FATAL_ERROR) {
return status;
}
/* Identify the stimulus for global reset/set for programming purpose: /* Identify the stimulus for global reset/set for programming purpose:
* - If only reset port is seen we turn on Reset * - If only reset port is seen we turn on Reset
@ -2124,7 +2135,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
/* Close the file stream */ /* Close the file stream */
fp.close(); fp.close();
return 0; return status;
} }

View File

@ -11,7 +11,11 @@
#include "vtr_assert.h" #include "vtr_assert.h"
#include "vtr_time.h" #include "vtr_time.h"
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
/* Headers from openfpgautil library */ /* Headers from openfpgautil library */
#include "openfpga_scale.h"
#include "openfpga_port.h" #include "openfpga_port.h"
#include "openfpga_digest.h" #include "openfpga_digest.h"
@ -279,15 +283,48 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(
fp << std::endl; fp << std::endl;
} }
void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, /**
const ConfigProtocol& config_protocol, * @brief Update the clock period of shift register chain by considering the constraints from simulation settings
const ModuleManager& module_manager, * - If the frequency is lower than the pre-computed bound, we should error out! Shift register chain cannot load the data completely
const ModuleId& top_module, * - If the frequency is higher than the pre-computed bound, we use the contrained frequency
const bool& fast_configuration, * @param sr_clock_port is the clock port which expect constraints
const bool& bit_value_to_skip, * @param sr_clock_period is the pre-constrained clock period. It is also the final clock period which will be return (if updated)
const FabricBitstream& fabric_bitstream, */
const float& prog_clock_period, static
const float& timescale) { int constrain_blwl_shift_register_clock_period_from_simulation_settings(const SimulationSetting& sim_settings,
const BasicPort& sr_clock_port,
const float& timescale,
float& sr_clock_period) {
for (const SimulationClockId& sim_clk : sim_settings.programming_shift_register_clocks()) {
/* Bypass all the clocks which does not match */
if (sim_settings.clock_port(sim_clk) == sr_clock_port) {
if (sr_clock_period > 0.5 * (1 / sim_settings.clock_frequency(sim_clk)) / timescale) {
VTR_LOG_ERROR("Constrained clock frequency for BL shift registers is lower than the minimum requirement (%g %s[Hz])! Shift register chain cannot load data completely!\n",
1. / (2. * sr_clock_period) / 1e6,
time_unit_to_string(1e6).c_str());
return CMD_EXEC_FATAL_ERROR;
} else {
sr_clock_period = 0.5 * (1. / sim_settings.clock_frequency(sim_clk)) / timescale;
VTR_LOG("Will use constrained clock frequency (=%g %s[Hz]) for %s.\n",
sim_settings.clock_frequency(sim_clk) / 1e6,
time_unit_to_string(1e6).c_str(),
sr_clock_port.get_name().c_str());
}
}
}
return CMD_EXEC_SUCCESS;
}
int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp,
const ConfigProtocol& config_protocol,
const SimulationSetting& sim_settings,
const ModuleManager& module_manager,
const ModuleId& top_module,
const bool& fast_configuration,
const bool& bit_value_to_skip,
const FabricBitstream& fabric_bitstream,
const float& prog_clock_period,
const float& timescale) {
ModulePortId en_port_id = module_manager.find_module_port(top_module, ModulePortId en_port_id = module_manager.find_module_port(top_module,
std::string(DECODER_ENABLE_PORT_NAME)); std::string(DECODER_ENABLE_PORT_NAME));
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
@ -313,13 +350,38 @@ void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
fast_configuration, fast_configuration,
bit_value_to_skip); bit_value_to_skip);
/* TODO: Consider auto-tuned clock period for now: /* Compute the auto-tuned clock period first, this is the lower bound of the shift register clock periods:
* - the BL/WL shift register clock only works in the second half of the programming clock period * - the BL/WL shift register clock only works in the second half of the programming clock period
* - add 2 idle clocks to avoid racing between programming clock and shift register clocks at edge * - add 2 idle clocks to avoid racing between programming clock and shift register clocks at edge
*/ */
float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale; float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale;
float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale; float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale;
VTR_LOG("Precomputed clock frequency (=%g %s[Hz]) for %s.\n",
1. / (2. * bl_sr_clock_period) / 1e6,
time_unit_to_string(1e6).c_str(),
bl_sr_clock_port.get_name().c_str());
VTR_LOG("Precomputed clock frequency (=%g %s[Hz]) for %s.\n",
1. / (2. * wl_sr_clock_period) / 1e6,
time_unit_to_string(1e6).c_str(),
wl_sr_clock_port.get_name().c_str());
if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings,
bl_sr_clock_port,
timescale,
bl_sr_clock_period)) {
return CMD_EXEC_FATAL_ERROR;
}
if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings,
wl_sr_clock_port,
timescale,
wl_sr_clock_period)) {
return CMD_EXEC_FATAL_ERROR;
}
if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) {
print_verilog_comment(fp, "----- BL Shift register clock generator -----"); print_verilog_comment(fp, "----- BL Shift register clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_bl_sr_port, bl_sr_clock_port, bl_sr_clock_period); print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_bl_sr_port, bl_sr_clock_port, bl_sr_clock_period);
@ -330,6 +392,8 @@ void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_wl_sr_port, wl_sr_clock_port, wl_sr_clock_period); print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_wl_sr_port, wl_sr_clock_port, wl_sr_clock_period);
} }
} }
return CMD_EXEC_SUCCESS;
} }
/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ /* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */

View File

@ -45,15 +45,16 @@ void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std::
/** /**
* @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL protocols * @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL protocols
*/ */
void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp,
const ConfigProtocol& config_protocol, const ConfigProtocol& config_protocol,
const ModuleManager& module_manager, const SimulationSetting& sim_settings,
const ModuleId& top_module, const ModuleManager& module_manager,
const bool& fast_configuration, const ModuleId& top_module,
const bool& bit_value_to_skip, const bool& fast_configuration,
const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip,
const float& prog_clock_period, const FabricBitstream& fabric_bitstream,
const float& timescale); const float& prog_clock_period,
const float& timescale);
/** /**
* @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol