pass current regression tests

This commit is contained in:
tangxifan 2019-10-30 19:10:36 -06:00
parent 55fbd72293
commit 7460dc8cab
6 changed files with 173 additions and 10 deletions

View File

@ -99,10 +99,18 @@ std::vector<bool> build_cmos_mux_bitstream(const CircuitLibrary& circuit_lib,
*/
for (const size_t& level : mux_graph.levels()) {
/* The encoder will convert the path_id to a binary number
* For example: when path_id=3 (use the 4th input), using a 4-input encoder
* the sram_bits will be the 4-digit binary number of 3: 0100
* For example: when path_id=3 (use the 4th input), using a 2-input encoder
* the sram_bits will be the 2-digit binary number of 3: 10
*/
std::vector<size_t> encoder_data;
/* Exception: there is only 1 memory at this level, bitstream will not be changed!!! */
if (1 == mux_graph.memories_at_level(level).size()) {
mux_bitstream.push_back(raw_bitstream[mux_graph.memories_at_level(level)[0]]);
continue;
}
/* Otherwise: we follow a regular recipe */
for (size_t mem_index = 0; mem_index < mux_graph.memories_at_level(level).size(); ++mem_index) {
/* Conversion rule: true = 1, false = 0 */
if (true == raw_bitstream[mux_graph.memories_at_level(level)[mem_index]]) {
@ -121,7 +129,7 @@ std::vector<bool> build_cmos_mux_bitstream(const CircuitLibrary& circuit_lib,
}
/* Build final mux bitstream */
for (const size_t& bit : encoder_addr) {
mux_bitstream.push_back((bool)bit);
mux_bitstream.push_back(1 == bit);
}
}

View File

@ -1004,6 +1004,7 @@ void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manag
/* Local port to record the LSB and MSB of each level, here, we deposite (0, 0) */
ModulePortId mux_module_sram_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_lib_name(mux_sram_ports[0]));
ModulePortId mux_module_sram_inv_port_id = module_manager.find_module_port(mux_module, circuit_lib.port_lib_name(mux_sram_ports[0]) + "_inv");
BasicPort lvl_addr_port(circuit_lib.port_lib_name(mux_sram_ports[0]), 0);
BasicPort lvl_data_port(decoder_data_port.get_name(), 0);
BasicPort lvl_data_inv_port(decoder_data_inv_port.get_name(), 0);
@ -1020,6 +1021,24 @@ void build_mux_module_local_encoders_and_memory_nets(ModuleManager& module_manag
lvl_data_port.rotate(data_size);
lvl_data_inv_port.rotate(data_size);
/* Exception: if the data size is one, we just need wires! */
if (1 == data_size) {
for (size_t pin_id = 0; pin_id < lvl_addr_port.pins().size(); ++pin_id) {
MuxMemId mem_id = MuxMemId(mem_net_cnt);
/* Set the module net source */
module_manager.add_module_net_source(mux_module, mux_mem_nets[mem_id], mux_module, 0, mux_module_sram_port_id, lvl_addr_port.pins()[pin_id]);
/* Update counter */
mem_net_cnt++;
MuxMemId mem_inv_id = MuxMemId(mem_inv_net_cnt);
/* Set the module net source */
module_manager.add_module_net_source(mux_module, mux_mem_inv_nets[mem_inv_id], mux_module, 0, mux_module_sram_inv_port_id, lvl_addr_port.pins()[pin_id]);
/* Update counter */
mem_inv_net_cnt++;
}
continue;
}
std::string decoder_module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size);
ModuleId decoder_module = module_manager.find_module(decoder_module_name);
VTR_ASSERT(ModuleId::INVALID() != decoder_module);

View File

@ -82,8 +82,8 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp,
* data_inv = ~data_inv
*/
if (1 == data_size) {
print_verilog_wire_connection(fp, addr_port, data_port, false);
print_verilog_wire_connection(fp, data_inv_port, data_port, true);
print_verilog_wire_connection(fp, data_port, addr_port, false);
print_verilog_wire_connection(fp, data_inv_port, addr_port, true);
print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
/* Put an end to the Verilog module */

View File

@ -266,13 +266,101 @@ void print_verilog_preconfig_top_module_connect_ios(std::fstream& fp,
/********************************************************************
* Impose the bitstream on the configuration memories
* This function uses 'assign' syntax to impost the bitstream at mem port
* while uses 'force' syntax to impost the bitstream at mem_inv port
*******************************************************************/
static
void print_verilog_preconfig_top_module_load_bitstream(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const BitstreamManager& bitstream_manager) {
print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----"));
void print_verilog_preconfig_top_module_assign_bitstream(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const BitstreamManager& bitstream_manager) {
/* Validate the file stream */
check_file_handler(fp);
print_verilog_comment(fp, std::string("----- Begin assign bitstream to configuration memories -----"));
for (const ConfigBlockId& config_block_id : bitstream_manager.blocks()) {
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(formal_verification_top_module_uut_name);
for (const ConfigBlockId& temp_block : block_hierarchy) {
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
/* Find the bit index in the parent block */
BasicPort config_data_port(bit_hierarchy_path + generate_configuration_chain_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
/* Wire it to the configuration bit: access both data out and data outb ports */
std::vector<size_t> config_data_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
}
print_verilog_wire_constant_values(fp, config_data_port, config_data_values);
}
fp << "initial begin" << std::endl;
for (const ConfigBlockId& config_block_id : bitstream_manager.blocks()) {
/* We only cares blocks with configuration bits */
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
continue;
}
/* Build the hierarchical path of the configuration bit in modules */
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
/* Ensure that this is the module we want to drop! */
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
block_hierarchy.erase(block_hierarchy.begin());
/* Build the full hierarchy path */
std::string bit_hierarchy_path(formal_verification_top_module_uut_name);
for (const ConfigBlockId& temp_block : block_hierarchy) {
bit_hierarchy_path += std::string(".");
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
}
bit_hierarchy_path += std::string(".");
/* Find the bit index in the parent block */
BasicPort config_datab_port(bit_hierarchy_path + generate_configuration_chain_inverted_data_out_name(),
bitstream_manager.block_bits(config_block_id).size());
std::vector<size_t> config_datab_values;
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
}
print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values);
}
fp << "end" << std::endl;
print_verilog_comment(fp, std::string("----- End assign bitstream to configuration memories -----"));
}
/********************************************************************
* Impose the bitstream on the configuration memories
* This function uses '$deposit' syntax to do so
*******************************************************************/
static
void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const BitstreamManager& bitstream_manager) {
/* Validate the file stream */
check_file_handler(fp);
print_verilog_comment(fp, std::string("----- Begin deposit bitstream to configuration memories -----"));
fp << "initial begin" << std::endl;
for (const ConfigBlockId& config_block_id : bitstream_manager.blocks()) {
@ -316,6 +404,35 @@ void print_verilog_preconfig_top_module_load_bitstream(std::fstream& fp,
}
fp << "end" << std::endl;
print_verilog_comment(fp, std::string("----- End deposit bitstream to configuration memories -----"));
}
/********************************************************************
* Impose the bitstream on the configuration memories
* We branch here for different simulators:
* 1. iVerilog Icarus prefers using 'assign' syntax to force the values
* 2. Mentor Modelsim prefers using '$deposit' syntax to do so
*******************************************************************/
static
void print_verilog_preconfig_top_module_load_bitstream(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const BitstreamManager& bitstream_manager) {
print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----"));
print_verilog_preprocessing_flag(fp, std::string(icarus_simulator_flag));
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_assign_bitstream(fp, module_manager, top_module, bitstream_manager);
fp << "`else" << std::endl;
/* Use assign syntax for Icarus simulator */
print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module, bitstream_manager);
print_verilog_endif(fp);
print_verilog_comment(fp, std::string("----- End load bitstream to configuration memories -----"));
}

View File

@ -682,6 +682,21 @@ void print_verilog_deposit_wire_constant_values(std::fstream& fp,
fp << ");" << std::endl;
}
/********************************************************************
* Generate a wire connection, that assigns constant values to a
* Verilog port
*******************************************************************/
void print_verilog_force_wire_constant_values(std::fstream& fp,
const BasicPort& output_port,
const std::vector<size_t>& const_values) {
/* Make sure we have a valid file handler*/
check_file_handler(fp);
fp << "\t";
fp << "force ";
fp << generate_verilog_port_constant_values(output_port, const_values);
fp << ";" << std::endl;
}
/********************************************************************
* Generate a wire connection for two Verilog ports

View File

@ -92,6 +92,10 @@ void print_verilog_deposit_wire_constant_values(std::fstream& fp,
const BasicPort& output_port,
const std::vector<size_t>& const_values);
void print_verilog_force_wire_constant_values(std::fstream& fp,
const BasicPort& output_port,
const std::vector<size_t>& const_values);
void print_verilog_wire_connection(std::fstream& fp,
const BasicPort& output_port,
const BasicPort& input_port,