add architecture decoder (for frame-based config memory) to Verilog writer
This commit is contained in:
parent
c696e3d20f
commit
5c5a044c68
|
@ -48,6 +48,7 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx,
|
||||||
openfpga_ctx.mutable_verilog_netlists(),
|
openfpga_ctx.mutable_verilog_netlists(),
|
||||||
openfpga_ctx.arch().circuit_lib,
|
openfpga_ctx.arch().circuit_lib,
|
||||||
openfpga_ctx.mux_lib(),
|
openfpga_ctx.mux_lib(),
|
||||||
|
openfpga_ctx.decoder_lib(),
|
||||||
g_vpr_ctx.device(),
|
g_vpr_ctx.device(),
|
||||||
openfpga_ctx.vpr_device_annotation(),
|
openfpga_ctx.vpr_device_annotation(),
|
||||||
openfpga_ctx.device_rr_gsb(),
|
openfpga_ctx.device_rr_gsb(),
|
||||||
|
|
|
@ -54,6 +54,7 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
|
||||||
NetlistManager& netlist_manager,
|
NetlistManager& netlist_manager,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const MuxLibrary& mux_lib,
|
const MuxLibrary& mux_lib,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
const DeviceContext& device_ctx,
|
const DeviceContext& device_ctx,
|
||||||
const VprDeviceAnnotation& device_annotation,
|
const VprDeviceAnnotation& device_annotation,
|
||||||
const DeviceRRGSB& device_rr_gsb,
|
const DeviceRRGSB& device_rr_gsb,
|
||||||
|
@ -90,7 +91,7 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
|
||||||
* Without the modules in the module manager, core logic generation is not possible!!!
|
* Without the modules in the module manager, core logic generation is not possible!!!
|
||||||
*/
|
*/
|
||||||
print_verilog_submodule(module_manager, netlist_manager,
|
print_verilog_submodule(module_manager, netlist_manager,
|
||||||
mux_lib, circuit_lib,
|
mux_lib, decoder_lib, circuit_lib,
|
||||||
submodule_dir_path,
|
submodule_dir_path,
|
||||||
options);
|
options);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "mux_library.h"
|
#include "mux_library.h"
|
||||||
|
#include "decoder_library.h"
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
#include "vpr_context.h"
|
#include "vpr_context.h"
|
||||||
#include "vpr_device_annotation.h"
|
#include "vpr_device_annotation.h"
|
||||||
|
@ -32,6 +33,7 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
|
||||||
NetlistManager& netlist_manager,
|
NetlistManager& netlist_manager,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const MuxLibrary& mux_lib,
|
const MuxLibrary& mux_lib,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
const DeviceContext& device_ctx,
|
const DeviceContext& device_ctx,
|
||||||
const VprDeviceAnnotation& device_annotation,
|
const VprDeviceAnnotation& device_annotation,
|
||||||
const DeviceRRGSB& device_rr_gsb,
|
const DeviceRRGSB& device_rr_gsb,
|
||||||
|
|
|
@ -37,6 +37,7 @@ constexpr char* LUTS_VERILOG_FILE_NAME = "luts.v";
|
||||||
constexpr char* ROUTING_VERILOG_FILE_NAME = "routing.v";
|
constexpr char* ROUTING_VERILOG_FILE_NAME = "routing.v";
|
||||||
constexpr char* MUXES_VERILOG_FILE_NAME = "muxes.v";
|
constexpr char* MUXES_VERILOG_FILE_NAME = "muxes.v";
|
||||||
constexpr char* LOCAL_ENCODER_VERILOG_FILE_NAME = "local_encoder.v";
|
constexpr char* LOCAL_ENCODER_VERILOG_FILE_NAME = "local_encoder.v";
|
||||||
|
constexpr char* ARCH_ENCODER_VERILOG_FILE_NAME = "arch_encoder.v";
|
||||||
constexpr char* MEMORIES_VERILOG_FILE_NAME = "memories.v";
|
constexpr char* MEMORIES_VERILOG_FILE_NAME = "memories.v";
|
||||||
constexpr char* WIRES_VERILOG_FILE_NAME = "wires.v";
|
constexpr char* WIRES_VERILOG_FILE_NAME = "wires.v";
|
||||||
constexpr char* ESSENTIALS_VERILOG_FILE_NAME = "inv_buf_passgate.v";
|
constexpr char* ESSENTIALS_VERILOG_FILE_NAME = "inv_buf_passgate.v";
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
* This file includes functions to generate Verilog modules of decoders
|
* This file includes functions to generate Verilog modules of decoders
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
/* TODO: merge verilog_decoder.c to this source file and rename to verilog_decoder.cpp */
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/* Headers from vtrutil library */
|
/* Headers from vtrutil library */
|
||||||
|
@ -15,6 +14,7 @@
|
||||||
#include "decoder_library_utils.h"
|
#include "decoder_library_utils.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
|
|
||||||
|
#include "openfpga_reserved_words.h"
|
||||||
#include "openfpga_naming.h"
|
#include "openfpga_naming.h"
|
||||||
|
|
||||||
#include "verilog_constants.h"
|
#include "verilog_constants.h"
|
||||||
|
@ -133,7 +133,6 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp,
|
||||||
print_verilog_module_end(fp, module_name);
|
print_verilog_module_end(fp, module_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
* This function will generate all the unique Verilog modules of local decoders for
|
* This function will generate all the unique Verilog modules of local decoders for
|
||||||
* the multiplexers used in a FPGA fabric
|
* the multiplexers used in a FPGA fabric
|
||||||
|
@ -227,4 +226,179 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana
|
||||||
VTR_LOG("Done\n");
|
VTR_LOG("Done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
* Create a Verilog module for a decoder used as a configuration protocol
|
||||||
|
* in FPGA architecture
|
||||||
|
*
|
||||||
|
* Address
|
||||||
|
* | | ... |
|
||||||
|
* v v v
|
||||||
|
* +-----------+
|
||||||
|
* Enable->/ \
|
||||||
|
* / Decoder \
|
||||||
|
* +-----------------+
|
||||||
|
* | | | ... | | |
|
||||||
|
* v v v v v v
|
||||||
|
* Data output
|
||||||
|
*
|
||||||
|
* The outputs are assumes to be one-hot codes (at most only one '1' exist)
|
||||||
|
* Considering this fact, there are only num_of_outputs conditions to be encoded.
|
||||||
|
* Therefore, the number of inputs is ceil(log(num_of_outputs)/log(2))
|
||||||
|
*
|
||||||
|
* The decoder has an enable signal which is active at logic '1'.
|
||||||
|
* When activated, the decoder will output decoding results to the data output port
|
||||||
|
* Otherwise, the data output port will be always all-zero
|
||||||
|
***************************************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_arch_decoder_module(std::fstream& fp,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
|
const DecoderId& decoder) {
|
||||||
|
/* Get the number of inputs */
|
||||||
|
size_t addr_size = decoder_lib.addr_size(decoder);
|
||||||
|
size_t data_size = decoder_lib.data_size(decoder);
|
||||||
|
|
||||||
|
/* Validate the FILE handler */
|
||||||
|
VTR_ASSERT(true == valid_file_stream(fp));
|
||||||
|
|
||||||
|
/* Create a name for the decoder */
|
||||||
|
std::string module_name = generate_frame_memory_decoder_subckt_name(addr_size, data_size);
|
||||||
|
|
||||||
|
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||||
|
ModuleId module_id = module_manager.find_module(module_name);
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
|
||||||
|
/* Find module ports */
|
||||||
|
/* Enable port */
|
||||||
|
ModulePortId enable_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ENABLE_PORT_NAME));
|
||||||
|
BasicPort enable_port = module_manager.module_port(module_id, enable_port_id);
|
||||||
|
/* Address port */
|
||||||
|
ModulePortId addr_port_id = module_manager.find_module_port(module_id, std::string(DECODER_ADDRESS_PORT_NAME));
|
||||||
|
BasicPort addr_port = module_manager.module_port(module_id, addr_port_id);
|
||||||
|
/* Find each output port */
|
||||||
|
ModulePortId data_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_PORT_NAME));
|
||||||
|
BasicPort data_port = module_manager.module_port(module_id, data_port_id);
|
||||||
|
/* Data port is registered. It should be outputted as
|
||||||
|
* output reg [lsb:msb] data
|
||||||
|
*/
|
||||||
|
BasicPort data_inv_port(std::string(DECODER_DATA_OUT_INV_PORT_NAME), data_size);
|
||||||
|
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||||
|
ModulePortId data_inv_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_OUT_INV_PORT_NAME));
|
||||||
|
data_inv_port = module_manager.module_port(module_id, data_inv_port_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dump module definition + ports */
|
||||||
|
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||||
|
/* Finish dumping ports */
|
||||||
|
|
||||||
|
print_verilog_comment(fp, std::string("----- BEGIN Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
|
||||||
|
|
||||||
|
/* Print the truth table of this decoder */
|
||||||
|
/* Internal logics */
|
||||||
|
/* Early exit: Corner case for data size = 1 the logic is very simple:
|
||||||
|
* data = addr;
|
||||||
|
* data_inv = ~data_inv
|
||||||
|
*/
|
||||||
|
if (1 == data_size) {
|
||||||
|
print_verilog_wire_connection(fp, data_port, addr_port, false);
|
||||||
|
|
||||||
|
/* Depend on if the inverted data output port is needed or not */
|
||||||
|
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||||
|
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 */
|
||||||
|
print_verilog_module_end(fp, module_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We use a magic number -1 as the addr=1 should be mapped to ...1
|
||||||
|
* Otherwise addr will map addr=1 to ..10
|
||||||
|
* Note that there should be a range for the shift operators
|
||||||
|
* We should narrow the encoding to be applied to a given set of data
|
||||||
|
* This will lead to that any addr which falls out of the op code of data
|
||||||
|
* will give a all-zero code
|
||||||
|
* For example:
|
||||||
|
* data is 5-bit while addr is 3-bit
|
||||||
|
* data=8'b0_0000 will be encoded to addr=3'b001;
|
||||||
|
* data=8'b0_0001 will be encoded to addr=3'b010;
|
||||||
|
* data=8'b0_0010 will be encoded to addr=3'b011;
|
||||||
|
* data=8'b0_0100 will be encoded to addr=3'b100;
|
||||||
|
* data=8'b0_1000 will be encoded to addr=3'b101;
|
||||||
|
* data=8'b1_0000 will be encoded to addr=3'b110;
|
||||||
|
* The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000;
|
||||||
|
*/
|
||||||
|
|
||||||
|
fp << "\t" << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
|
||||||
|
fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << "1'b1) begin" << std::endl;
|
||||||
|
fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
|
||||||
|
/* Create a string for addr and data */
|
||||||
|
for (size_t i = 0; i < data_size; ++i) {
|
||||||
|
fp << "\t\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size));
|
||||||
|
fp << " : ";
|
||||||
|
fp << generate_verilog_port_constant_values(data_port, ito1hot_vec(i, data_size));
|
||||||
|
fp << ";" << std::endl;
|
||||||
|
}
|
||||||
|
fp << "\t\t\t" << "default : ";
|
||||||
|
fp << generate_verilog_port_constant_values(data_port, ito1hot_vec(data_size - 1, data_size));
|
||||||
|
fp << ";" << std::endl;
|
||||||
|
fp << "\t\t" << "endcase" << std::endl;
|
||||||
|
fp << "\t" << "end" << std::endl;
|
||||||
|
|
||||||
|
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||||
|
print_verilog_wire_connection(fp, data_inv_port, data_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 */
|
||||||
|
print_verilog_module_end(fp, module_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
* This function will generate all the unique Verilog modules of decoders for
|
||||||
|
* configuration protocols in a FPGA fabric
|
||||||
|
* It will generate these decoder Verilog modules using behavioral description.
|
||||||
|
* Note that the implementation of local decoders can be dependent on the technology
|
||||||
|
* and standard cell libraries.
|
||||||
|
* Therefore, behavioral Verilog is used and the local decoders should be synthesized
|
||||||
|
* before running the back-end flow for FPGA fabric
|
||||||
|
* See more details in the function print_verilog_arch_decoder() for more details
|
||||||
|
***************************************************************************************/
|
||||||
|
void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager,
|
||||||
|
NetlistManager& netlist_manager,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
|
const std::string& submodule_dir) {
|
||||||
|
std::string verilog_fname(submodule_dir + std::string(ARCH_ENCODER_VERILOG_FILE_NAME));
|
||||||
|
|
||||||
|
/* Create the file stream */
|
||||||
|
std::fstream fp;
|
||||||
|
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
|
||||||
|
|
||||||
|
check_file_stream(verilog_fname.c_str(), fp);
|
||||||
|
|
||||||
|
/* Print out debugging information for if the file is not opened/created properly */
|
||||||
|
VTR_LOG("Writing Verilog netlist for configuration decoders '%s'...",
|
||||||
|
verilog_fname.c_str());
|
||||||
|
|
||||||
|
print_verilog_file_header(fp, "Decoders for fabric configuration protocol ");
|
||||||
|
|
||||||
|
/* Generate Verilog modules for the found unique local encoders */
|
||||||
|
for (const auto& decoder : decoder_lib.decoders()) {
|
||||||
|
print_verilog_arch_decoder_module(fp, module_manager, decoder_lib, decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the file stream */
|
||||||
|
fp.close();
|
||||||
|
|
||||||
|
/* Add fname to the netlist name list */
|
||||||
|
NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname);
|
||||||
|
VTR_ASSERT(NetlistId::INVALID() != nlist_id);
|
||||||
|
netlist_manager.set_netlist_type(nlist_id, NetlistManager::SUBMODULE_NETLIST);
|
||||||
|
|
||||||
|
VTR_LOG("Done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
#include "mux_graph.h"
|
#include "mux_graph.h"
|
||||||
#include "mux_library.h"
|
#include "mux_library.h"
|
||||||
|
#include "decoder_library.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "netlist_manager.h"
|
#include "netlist_manager.h"
|
||||||
|
|
||||||
|
@ -27,6 +28,12 @@ void print_verilog_submodule_mux_local_decoders(const ModuleManager& module_mana
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const std::string& submodule_dir);
|
const std::string& submodule_dir);
|
||||||
|
|
||||||
|
void print_verilog_submodule_arch_decoders(const ModuleManager& module_manager,
|
||||||
|
NetlistManager& netlist_manager,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
|
const std::string& submodule_dir);
|
||||||
|
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace openfpga {
|
||||||
void print_verilog_submodule(ModuleManager& module_manager,
|
void print_verilog_submodule(ModuleManager& module_manager,
|
||||||
NetlistManager& netlist_manager,
|
NetlistManager& netlist_manager,
|
||||||
const MuxLibrary& mux_lib,
|
const MuxLibrary& mux_lib,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const std::string& submodule_dir,
|
const std::string& submodule_dir,
|
||||||
const FabricVerilogOption& fpga_verilog_opts) {
|
const FabricVerilogOption& fpga_verilog_opts) {
|
||||||
|
@ -49,6 +50,12 @@ void print_verilog_submodule(ModuleManager& module_manager,
|
||||||
submodule_dir,
|
submodule_dir,
|
||||||
circuit_lib);
|
circuit_lib);
|
||||||
|
|
||||||
|
/* Decoders for architecture */
|
||||||
|
print_verilog_submodule_arch_decoders(const_cast<const ModuleManager&>(module_manager),
|
||||||
|
netlist_manager,
|
||||||
|
decoder_lib,
|
||||||
|
submodule_dir);
|
||||||
|
|
||||||
/* Routing multiplexers */
|
/* Routing multiplexers */
|
||||||
/* NOTE: local decoders generation must go before the MUX generation!!!
|
/* NOTE: local decoders generation must go before the MUX generation!!!
|
||||||
* because local decoders modules will be instanciated in the MUX modules
|
* because local decoders modules will be instanciated in the MUX modules
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "netlist_manager.h"
|
#include "netlist_manager.h"
|
||||||
#include "mux_library.h"
|
#include "mux_library.h"
|
||||||
|
#include "decoder_library.h"
|
||||||
#include "fabric_verilog_options.h"
|
#include "fabric_verilog_options.h"
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
|
@ -19,6 +20,7 @@ namespace openfpga {
|
||||||
void print_verilog_submodule(ModuleManager& module_manager,
|
void print_verilog_submodule(ModuleManager& module_manager,
|
||||||
NetlistManager& netlist_manager,
|
NetlistManager& netlist_manager,
|
||||||
const MuxLibrary& mux_lib,
|
const MuxLibrary& mux_lib,
|
||||||
|
const DecoderLibrary& decoder_lib,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const std::string& submodule_dir,
|
const std::string& submodule_dir,
|
||||||
const FabricVerilogOption& fpga_verilog_opts);
|
const FabricVerilogOption& fpga_verilog_opts);
|
||||||
|
|
Loading…
Reference in New Issue