[OpenFPGA Tool] Add edge triggered attribute to circuit library definition. Better support for using CCFF in frame-based protocol

This commit is contained in:
tangxifan 2020-09-23 20:27:52 -06:00
parent 8e4e66038a
commit 064678fe32
9 changed files with 81 additions and 29 deletions

View File

@ -942,6 +942,12 @@ bool CircuitLibrary::port_is_config_enable(const CircuitPortId& circuit_port_id)
return port_is_config_enable_[circuit_port_id];
}
bool CircuitLibrary::port_is_edge_triggered(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
return port_is_edge_triggered_[circuit_port_id];
}
/* Return a flag if the port is used during programming a FPGA in a circuit model */
bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
@ -1493,6 +1499,15 @@ void CircuitLibrary::set_port_is_config_enable(const CircuitPortId& circuit_port
return;
}
/* Set the is_edge_triggered for a port of a circuit model */
void CircuitLibrary::set_port_is_edge_triggered(const CircuitPortId& circuit_port_id,
const bool& is_edge_triggered) {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
port_is_edge_triggered_[circuit_port_id] = is_edge_triggered;
return;
}
/* Set the is_prog for a port of a circuit model */
void CircuitLibrary::set_port_is_prog(const CircuitPortId& circuit_port_id,
const bool& is_prog) {

View File

@ -91,15 +91,16 @@
* 9. port_is_reset: specify if this port is a reset signal which needs special pulse widths in testbenches
* 10. port_is_set: specify if this port is a set signal which needs special pulse widths in testbenches
* 11. port_is_config_enable: specify if this port is a config_enable signal which needs special pulse widths in testbenches
* 12. port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches
* 13. port_tri_state_model_name: the name of circuit model linked to tri-state the port
* 14. port_tri_state_model_ids_: the Id of circuit model linked to tri-state the port
* 15. port_inv_model_names_: the name of inverter circuit model linked to the port
* 16. port_inv_model_ids_: the Id of inverter circuit model linked to the port
* 17. port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port
* 18. port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used
* 19. port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used
* 20. port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains
* 12. port_is_edge_triggered: specify if this port is triggerd by edges like the clock signal of a D-type flip-flop
* 13. port_is_prog: specify if this port is for FPGA programming use which needs special pulse widths in testbenches
* 14. port_tri_state_model_name: the name of circuit model linked to tri-state the port
* 15. port_tri_state_model_ids_: the Id of circuit model linked to tri-state the port
* 16. port_inv_model_names_: the name of inverter circuit model linked to the port
* 17. port_inv_model_ids_: the Id of inverter circuit model linked to the port
* 18. port_tri_state_map_: only applicable to inputs of LUTs, the tri-state map applied to each pin of this port
* 19. port_lut_frac_level_: only applicable to outputs of LUTs, indicate which level of outputs inside LUT multiplexing structure will be used
* 20. port_lut_output_mask_: only applicable to outputs of LUTs, indicate which output at an internal level of LUT multiplexing structure will be used
* 21. port_sram_orgz_: only applicable to SRAM ports, indicate how the SRAMs will be organized, either memory decoders or scan-chains
*
* ------ Delay information ------
* 1. delay_types_: type of pin-to-pin delay, either rising_edge of falling_edge
@ -284,6 +285,7 @@ class CircuitLibrary {
bool port_is_reset(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_edge_triggered(const CircuitPortId& circuit_port_id) const;
bool port_is_prog(const CircuitPortId& circuit_port_id) const;
size_t port_lut_frac_level(const CircuitPortId& circuit_port_id) const;
std::vector<size_t> port_lut_output_mask(const CircuitPortId& circuit_port_id) const;
@ -364,6 +366,8 @@ class CircuitLibrary {
const bool& is_set);
void set_port_is_config_enable(const CircuitPortId& circuit_port_id,
const bool& is_config_enable);
void set_port_is_edge_triggered(const CircuitPortId& circuit_port_id,
const bool& is_edge_triggered);
void set_port_is_prog(const CircuitPortId& circuit_port_id,
const bool& is_prog);
void set_port_tri_state_model_name(const CircuitPortId& circuit_port_id,
@ -550,6 +554,7 @@ class CircuitLibrary {
vtr::vector<CircuitPortId, bool> port_is_reset_;
vtr::vector<CircuitPortId, bool> port_is_set_;
vtr::vector<CircuitPortId, bool> port_is_config_enable_;
vtr::vector<CircuitPortId, bool> port_is_edge_triggered_;
vtr::vector<CircuitPortId, bool> port_is_prog_;
vtr::vector<CircuitPortId, std::string> port_tri_state_model_names_;
vtr::vector<CircuitPortId, CircuitModelId> port_tri_state_model_ids_;

View File

@ -564,6 +564,9 @@ void read_xml_circuit_port(pugi::xml_node& xml_port,
/* Identify if the port is to enable programming for FPGAs, by default it is NOT */
circuit_lib.set_port_is_config_enable(port, get_attribute(xml_port, "is_config_enable", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Identify if the port is to triggered by edges, by default it is NOT */
circuit_lib.set_port_is_edge_triggered(port, get_attribute(xml_port, "is_edge_triggered", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
/* Find the name of circuit model that this port is linked to */
circuit_lib.set_port_tri_state_model_name(port, get_attribute(xml_port, "circuit_model_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());

View File

@ -207,6 +207,10 @@ void write_xml_circuit_port(std::fstream& fp,
write_xml_attribute(fp, "is_config_enable", "true");
}
if (true == circuit_lib.port_is_edge_triggered(port)) {
write_xml_attribute(fp, "is_edge_triggered", "true");
}
/* Output the name of circuit model that this port is linked to */
if (!circuit_lib.port_tri_state_model_name(port).empty()) {
write_xml_attribute(fp, "circuit_model_name", circuit_lib.port_tri_state_model_name(port).c_str());

View File

@ -97,7 +97,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
openfpga_ctx.vpr_netlist_annotation(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.simulation_setting(),
openfpga_ctx.arch().config_protocol.type(),
openfpga_ctx.arch().config_protocol,
options);
/* TODO: should identify the error code from internal function execution */

View File

@ -156,7 +156,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
const VprNetlistAnnotation &netlist_annotation,
const CircuitLibrary &circuit_lib,
const SimulationSetting &simulation_setting,
const e_config_protocol_type &config_protocol_type,
const ConfigProtocol &config_protocol,
const VerilogTestbenchOption &options) {
vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for FPGA fabric\n");
@ -205,7 +205,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX);
print_verilog_top_testbench(module_manager,
bitstream_manager, fabric_bitstream,
config_protocol_type,
config_protocol,
circuit_lib, global_ports,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,
@ -225,7 +225,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
src_dir_path,
atom_ctx, place_ctx, io_location_map,
module_manager,
config_protocol_type,
config_protocol.type(),
bitstream_manager.num_bits(),
simulation_setting.num_clock_cycles(),
simulation_setting.programming_clock_frequency(),

View File

@ -10,6 +10,7 @@
#include "mux_library.h"
#include "decoder_library.h"
#include "circuit_library.h"
#include "config_protocol.h"
#include "vpr_context.h"
#include "vpr_device_annotation.h"
#include "device_rr_gsb.h"
@ -49,7 +50,7 @@ void fpga_verilog_testbench(const ModuleManager& module_manager,
const VprNetlistAnnotation& netlist_annotation,
const CircuitLibrary& circuit_lib,
const SimulationSetting& simulation_parameters,
const e_config_protocol_type& config_protocol_type,
const ConfigProtocol& config_protocol,
const VerilogTestbenchOption& options);

View File

@ -153,6 +153,8 @@ void print_verilog_top_testbench_memory_bank_port(std::fstream& fp,
*******************************************************************/
static
void print_verilog_top_testbench_frame_decoder_port(std::fstream& fp,
const ConfigProtocol& config_protocol,
const CircuitLibrary& circuit_lib,
const ModuleManager& module_manager,
const ModuleId& top_module) {
/* Validate the file stream */
@ -174,15 +176,32 @@ void print_verilog_top_testbench_frame_decoder_port(std::fstream& fp,
fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl;
/* Wire the INVERTED configuration done signal to the enable signal !!! */
print_verilog_comment(fp, std::string("---- Wire enable port of frame-based decoder to inverted configuration done signal -----"));
ModulePortId en_port_id = module_manager.find_module_port(top_module,
std::string(DECODER_ENABLE_PORT_NAME));
BasicPort en_port = module_manager.module_port(top_module, en_port_id);
BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1);
fp << generate_verilog_port(VERILOG_PORT_WIRE, en_port) << ";" << std::endl;
print_verilog_wire_connection(fp, en_port, config_done_port, true);
/* Find the circuit model of configurable memory
* Spot its BL port and generate stimuli based on BL port's attribute:
* - If the BL port is triggered by edge, use the inverted programming clock signal
* - If the BL port is a regular port, use the inverted configuration done signal
*/
const CircuitModelId& mem_model = config_protocol.memory_model();
VTR_ASSERT(true == circuit_lib.valid_model_id(mem_model));
std::vector<CircuitPortId> mem_model_bl_ports = circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_BL);
VTR_ASSERT(1 == mem_model_bl_ports.size());
if (true == circuit_lib.port_is_edge_triggered(mem_model_bl_ports[0])) {
VTR_ASSERT_SAFE(false == circuit_lib.port_is_edge_triggered(mem_model_bl_ports[0]));
BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME), 1);
print_verilog_comment(fp, std::string("---- Wire enable port of frame-based decoder to inverted programming clock signal -----"));
fp << generate_verilog_port(VERILOG_PORT_WIRE, en_port) << ";" << std::endl;
print_verilog_wire_connection(fp, en_port, prog_clock_port, true);
} else {
BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1);
print_verilog_comment(fp, std::string("---- Wire enable port of frame-based decoder to inverted configuration done signal -----"));
fp << generate_verilog_port(VERILOG_PORT_WIRE, en_port) << ";" << std::endl;
print_verilog_wire_connection(fp, en_port, config_done_port, true);
}
}
/********************************************************************
@ -190,10 +209,11 @@ void print_verilog_top_testbench_frame_decoder_port(std::fstream& fp,
*******************************************************************/
static
void print_verilog_top_testbench_config_protocol_port(std::fstream& fp,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const CircuitLibrary& circuit_lib,
const ModuleManager& module_manager,
const ModuleId& top_module) {
switch(sram_orgz_type) {
switch(config_protocol.type()) {
case CONFIG_MEM_STANDALONE:
print_verilog_top_testbench_flatten_memory_port(fp, module_manager, top_module);
break;
@ -204,7 +224,8 @@ void print_verilog_top_testbench_config_protocol_port(std::fstream& fp,
print_verilog_top_testbench_memory_bank_port(fp, module_manager, top_module);
break;
case CONFIG_MEM_FRAME_BASED:
print_verilog_top_testbench_frame_decoder_port(fp, module_manager, top_module);
print_verilog_top_testbench_frame_decoder_port(fp, config_protocol, circuit_lib,
module_manager, top_module);
break;
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
@ -435,7 +456,8 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const CircuitLibrary& circuit_lib,
const std::string& circuit_name){
/* Validate the file stream */
valid_file_stream(fp);
@ -509,7 +531,7 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
fp << generate_verilog_port(VERILOG_PORT_REG, set_port) << ";" << std::endl;
/* Configuration ports depend on the organization of SRAMs */
print_verilog_top_testbench_config_protocol_port(fp, sram_orgz_type,
print_verilog_top_testbench_config_protocol_port(fp, config_protocol, circuit_lib,
module_manager, top_module);
/* Create a clock port if the benchmark have one but not in the default name!
@ -1459,7 +1481,7 @@ void print_verilog_top_testbench_bitstream(std::fstream& fp,
void print_verilog_top_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const AtomContext& atom_ctx,
@ -1498,13 +1520,14 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* Start of testbench */
print_verilog_top_testbench_ports(fp, module_manager, top_module,
atom_ctx, netlist_annotation, clock_port_names,
sram_orgz_type, circuit_name);
config_protocol, circuit_lib,
circuit_name);
/* Find the clock period */
float prog_clock_period = (1./simulation_parameters.programming_clock_frequency());
float op_clock_period = (1./simulation_parameters.operating_clock_frequency());
/* Estimate the number of configuration clock cycles */
size_t num_config_clock_cycles = calculate_num_config_clock_cycles(sram_orgz_type,
size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(),
fast_configuration,
bitstream_manager,
fabric_bitstream);
@ -1543,11 +1566,11 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* Print tasks used for loading bitstreams */
print_verilog_top_testbench_load_bitstream_task(fp,
sram_orgz_type,
config_protocol.type(),
module_manager, top_module);
/* load bitstream to FPGA fabric in a configuration phase */
print_verilog_top_testbench_bitstream(fp, sram_orgz_type,
print_verilog_top_testbench_bitstream(fp, config_protocol.type(),
fast_configuration,
module_manager, top_module,
bitstream_manager, fabric_bitstream);

View File

@ -10,6 +10,7 @@
#include "bitstream_manager.h"
#include "fabric_bitstream.h"
#include "circuit_library.h"
#include "config_protocol.h"
#include "vpr_context.h"
#include "io_location_map.h"
#include "vpr_netlist_annotation.h"
@ -25,7 +26,7 @@ namespace openfpga {
void print_verilog_top_testbench(const ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const AtomContext& atom_ctx,