diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp index 7fe3bf2df..cabd6ba00 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp @@ -304,6 +304,35 @@ bool module_net_is_local_wire(const ModuleManager& module_manager, return true; } +/******************************************************************** + * Identify if a net is an output short connection inside a module: + * The short connection is defined as the direct connection + * between two outputs port of the module + * + * module + * +-----------------------------+ + * | + * src------>+--------------->|--->outputA + * | | + * | | + * +--------------->|--->outputB + * +-----------------------------+ + + *******************************************************************/ +bool module_net_include_output_short_connection(const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net) { + /* Check all the sink modules of the net */ + size_t contain_num_module_output = 0; + for (ModuleId sink_module : module_manager.net_sink_modules(module_id, module_net)) { + if (module_id == sink_module) { + contain_num_module_output++; + } + } + + /* If we have found more than 1 module outputs, it indicated output short connection! */ + return (1 < contain_num_module_output); +} + /******************************************************************** * Identify if a net is a local short connection inside a module: * The short connection is defined as the direct connection diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h index 5156e7af2..a44abbfc4 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h @@ -50,6 +50,9 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager, bool module_net_is_local_wire(const ModuleManager& module_manager, const ModuleId& module_id, const ModuleNetId& module_net); +bool module_net_include_output_short_connection(const ModuleManager& module_manager, + const ModuleId& module_id, const ModuleNetId& module_net); + bool module_net_include_local_short_connection(const ModuleManager& module_manager, const ModuleId& module_id, const ModuleNetId& module_net); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.cpp index 02dca4351..718b47cdb 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_memory_modules.cpp @@ -106,16 +106,20 @@ void add_module_output_nets_to_mem_modules(ModuleManager& module_manager, * j-th pin of output port of the i-th child module is wired to the j + i*W -th * pin of output port of the memory module, where W is the size of port * 3. It assumes fixed port name for output ports + * + * We cache the module nets that have been created because they will be used later ********************************************************************/ static -void add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, - const ModuleId& mem_module, - const std::string& mem_module_output_name, - const CircuitLibrary& circuit_lib, - const CircuitPortId& circuit_port, - const ModuleId& child_module, - const size_t& child_index, - const size_t& child_instance) { +std::vector add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, + const ModuleId& mem_module, + const std::string& mem_module_output_name, + const CircuitLibrary& circuit_lib, + const CircuitPortId& circuit_port, + const ModuleId& child_module, + const size_t& child_index, + const size_t& child_instance) { + std::vector module_nets; + /* Wire inputs of parent module to inputs of child modules */ ModulePortId src_port_id = module_manager.find_module_port(child_module, circuit_lib.port_lib_name(circuit_port)); ModulePortId sink_port_id = module_manager.find_module_port(mem_module, mem_module_output_name); @@ -128,7 +132,12 @@ void add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, /* Sink node of the input net is the input of sram module */ size_t sink_pin_id = child_index * circuit_lib.port_size(circuit_port) + module_manager.module_port(mem_module, sink_port_id).pins()[pin_id]; module_manager.add_module_net_sink(mem_module, net, mem_module, 0, sink_port_id, sink_pin_id); + + /* Cache the nets */ + module_nets.push_back(net); } + + return module_nets; } /******************************************************************** @@ -155,9 +164,13 @@ void add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, static void add_module_nets_to_cmos_memory_chain_module(ModuleManager& module_manager, const ModuleId& parent_module, + const std::vector& output_nets, const CircuitLibrary& circuit_lib, const CircuitPortId& model_input_port, const CircuitPortId& model_output_port) { + /* Counter for the nets */ + size_t net_counter = 0; + for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { ModuleId net_src_module_id; size_t net_src_instance_id; @@ -203,11 +216,21 @@ void add_module_nets_to_cmos_memory_chain_module(ModuleManager& module_manager, /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = module_manager.create_module_net(parent_module); + ModuleNetId net; + if (0 == mem_index) { + net = module_manager.create_module_net(parent_module); + } else { + net = output_nets[net_counter]; + } /* Add net source */ module_manager.add_module_net_source(parent_module, net, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + + /* Update net counter */ + if (0 < mem_index) { + net_counter++; + } } } @@ -237,12 +260,17 @@ void add_module_nets_to_cmos_memory_chain_module(ModuleManager& module_manager, /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { /* Create a net and add source and sink to it */ - ModuleNetId net = module_manager.create_module_net(parent_module); + ModuleNetId net = output_nets[net_counter]; /* Add net source */ module_manager.add_module_net_source(parent_module, net, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); /* Add net sink */ module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + + /* Update net counter */ + net_counter++; } + + VTR_ASSERT(net_counter == output_nets.size()); } /********************************************************************* @@ -381,6 +409,9 @@ void build_memory_chain_module(ModuleManager& module_manager, /* Find the sram module in the module manager */ ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + /* Cache the output nets for non-inverted data output */ + std::vector mem_output_nets; + /* Instanciate each submodule */ for (size_t i = 0; i < num_mems; ++i) { size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); @@ -396,13 +427,18 @@ void build_memory_chain_module(ModuleManager& module_manager, VTR_ASSERT( 1 == iport); port_name = generate_configuration_chain_inverted_data_out_name(); } - add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, port_name, circuit_lib, sram_output_ports[iport], - sram_mem_module, i, sram_mem_instance); + std::vector output_nets = add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, + port_name, circuit_lib, sram_output_ports[iport], + sram_mem_module, i, sram_mem_instance); + /* Cache only for regular data outputs */ + if (0 == iport) { + mem_output_nets.insert(mem_output_nets.end(), output_nets.begin(), output_nets.end()); + } } } /* Build module nets to wire the configuration chain */ - add_module_nets_to_cmos_memory_chain_module(module_manager, mem_module, + add_module_nets_to_cmos_memory_chain_module(module_manager, mem_module, mem_output_nets, circuit_lib, sram_input_ports[0], sram_output_ports[0]); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c index 1f2d6c3b3..642ac9310 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c @@ -113,7 +113,7 @@ void write_include_netlists (char* src_dir_formatted, top_testbench_verilog_file_postfix); fprintf(fp, "`elsif %s\n", autochecked_simulation_flag); */ - fprintf(fp, "`include \"%s%s%s\"\n", src_dir_formatted, + fprintf(fp, "\t`include \"%s%s%s\"\n", src_dir_formatted, chomped_circuit_name, autocheck_top_testbench_verilog_file_postfix); fprintf(fp, "`endif\n"); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp index 2a495e91a..3a4bebcf8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_module_writer.cpp @@ -169,6 +169,50 @@ std::vector find_verilog_module_local_wires(const ModuleManager& modu return local_wires; } +/******************************************************************** + * Print a Verilog wire connection + * We search all the sinks of the net, + * if we find a module output, we try to find the next module output + * among the sinks of the net + * For each module output (except the first one), we print a wire connection + *******************************************************************/ +static +void print_verilog_module_output_short_connection(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id, + const ModuleNetId& module_net) { + /* Ensure a valid file stream */ + check_file_handler(fp); + + bool first_port = true; + BasicPort src_port; + + /* We have found a module input, now check all the sink modules of the net */ + for (ModuleNetSinkId net_sink : module_manager.module_net_sinks(module_id, module_net)) { + ModuleId sink_module = module_manager.net_sink_modules(module_id, module_net)[net_sink]; + if (module_id != sink_module) { + continue; + } + + /* Find the sink port and pin information */ + ModulePortId sink_port_id = module_manager.net_sink_ports(module_id, module_net)[net_sink]; + size_t sink_pin = module_manager.net_sink_pins(module_id, module_net)[net_sink]; + BasicPort sink_port(module_manager.module_port(module_id, sink_port_id).get_name(), sink_pin, sink_pin); + + /* For the first module output, this is the source port, we do nothing and go to the next */ + if (true == first_port) { + src_port = sink_port; + /* Flip the flag */ + first_port = false; + continue; + } + + /* We need to print a wire connection here */ + print_verilog_wire_connection(fp, sink_port, src_port, false); + } +} + + /******************************************************************** * Print a Verilog wire connection * We search all the sources of the net, @@ -242,6 +286,36 @@ void print_verilog_module_local_short_connections(std::fstream& fp, } } +/******************************************************************** + * Print output short connections inside a Verilog module + * The output short connection is defined as the direct connection + * between two output ports of the module + * This type of connection is not covered when printing Verilog instances + * Therefore, they are covered in this function + * + * module + * +-----------------------------+ + * | + * src------>+--------------->|--->outputA + * | | + * | | + * +--------------->|--->outputB + * +-----------------------------+ + *******************************************************************/ +static +void print_verilog_module_output_short_connections(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& module_id) { + /* Local wires come from the child modules */ + for (ModuleNetId module_net : module_manager.module_nets(module_id)) { + /* We only care the nets that indicate short connections */ + if (false == module_net_include_output_short_connection(module_manager, module_id, module_net)) { + continue; + } + print_verilog_module_output_short_connection(fp, module_manager, module_id, module_net); + } +} + /******************************************************************** * Write a Verilog instance to a file * This function will name the input and output connections to @@ -372,6 +446,8 @@ void write_verilog_module_to_file(std::fstream& fp, /* Print local connection (from module inputs to output! */ print_verilog_module_local_short_connections(fp, module_manager, module_id); + + print_verilog_module_output_short_connections(fp, module_manager, module_id); /* Print an empty line as splitter */ fp << std::endl; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_testbench.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_testbench.cpp index e5c89dd8f..644df5246 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_testbench.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_top_testbench.cpp @@ -547,7 +547,7 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, print_verilog_comment(fp, std::string("----- Actual operating clock is triggered only when " + config_done_port.get_name() + " is enabled -----")); fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, op_clock_port); fp << " = " << generate_verilog_port(VERILOG_PORT_CONKT, op_clock_register_port); - fp << " & (~" << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port) << ")"; + fp << " & " << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); fp << ";" << std::endl; fp << std::endl;