[FPGA-Verilog] Now consider clock constraints for BL/WL shift registers
This commit is contained in:
parent
95b877924a
commit
82ed6b177b
|
@ -11,6 +11,9 @@
|
|||
#include "vtr_assert.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_port.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
@ -1121,8 +1124,9 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp,
|
|||
* 1. the enable signal
|
||||
*******************************************************************/
|
||||
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 SimulationSetting& sim_settings,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const bool& fast_configuration,
|
||||
|
@ -1140,9 +1144,9 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f
|
|||
case CONFIG_MEM_SCAN_CHAIN:
|
||||
break;
|
||||
case CONFIG_MEM_QL_MEMORY_BANK:
|
||||
print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp,
|
||||
config_protocol,
|
||||
module_manager,top_module,
|
||||
return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp,
|
||||
config_protocol, sim_settings,
|
||||
module_manager, top_module,
|
||||
fast_configuration, bit_value_to_skip, fabric_bitstream,
|
||||
prog_clock_period, timescale);
|
||||
break;
|
||||
|
@ -1166,6 +1170,8 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f
|
|||
"Invalid SRAM organization type!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -1974,13 +1980,18 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
|
|||
VERILOG_SIM_TIMESCALE);
|
||||
|
||||
/* Generate stimuli for programming interface */
|
||||
print_verilog_top_testbench_configuration_protocol_stimulus(fp,
|
||||
config_protocol,
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
status = print_verilog_top_testbench_configuration_protocol_stimulus(fp,
|
||||
config_protocol, simulation_parameters,
|
||||
module_manager, top_module,
|
||||
fast_configuration, bit_value_to_skip, fabric_bitstream,
|
||||
prog_clock_period,
|
||||
VERILOG_SIM_TIMESCALE);
|
||||
|
||||
if (status == CMD_EXEC_FATAL_ERROR) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Identify the stimulus for global reset/set for programming purpose:
|
||||
* - If only reset port is seen we turn on Reset
|
||||
* - If only set port is seen we turn on Reset
|
||||
|
@ -2124,7 +2135,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
|
|||
/* Close the file stream */
|
||||
fp.close();
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
#include "vtr_assert.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_scale.h"
|
||||
#include "openfpga_port.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
|
@ -279,8 +283,41 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(
|
|||
fp << std::endl;
|
||||
}
|
||||
|
||||
void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp,
|
||||
/**
|
||||
* @brief Update the clock period of shift register chain by considering the constraints from simulation settings
|
||||
* - If the frequency is lower than the pre-computed bound, we should error out! Shift register chain cannot load the data completely
|
||||
* - If the frequency is higher than the pre-computed bound, we use the contrained frequency
|
||||
* @param sr_clock_port is the clock port which expect constraints
|
||||
* @param sr_clock_period is the pre-constrained clock period. It is also the final clock period which will be return (if updated)
|
||||
*/
|
||||
static
|
||||
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,
|
||||
|
@ -313,13 +350,38 @@ void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
|
|||
fast_configuration,
|
||||
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
|
||||
* - 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 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()) {
|
||||
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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */
|
||||
|
|
|
@ -45,8 +45,9 @@ 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
|
||||
*/
|
||||
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 SimulationSetting& sim_settings,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const bool& fast_configuration,
|
||||
|
|
Loading…
Reference in New Issue