Merge pull request #62 from LNIS-Projects/dev
Simplify fabric key where users just need to provide alias; start porting FPGA-SPICE
This commit is contained in:
commit
f246da6538
|
@ -67,5 +67,4 @@ The following is an example of a fabric key generate by OpenFPGA for a 2 :math:`
|
|||
<key id="30" name="cbx_1__1_" value="0" alias="cbx_1__1_"/>
|
||||
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1_3"/>
|
||||
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0_2"/>
|
||||
<key id="33" name="decoder6to33" value="0"/>
|
||||
</fabric_key>
|
||||
|
|
|
@ -29,9 +29,7 @@ void read_xml_component_key(pugi::xml_node& xml_component_key,
|
|||
|
||||
/* Find the id of component key */
|
||||
const size_t& id = get_attribute(xml_component_key, "id", loc_data).as_int();
|
||||
const std::string& name = get_attribute(xml_component_key, "name", loc_data).as_string();
|
||||
const size_t& value = get_attribute(xml_component_key, "value", loc_data).as_int();
|
||||
|
||||
|
||||
if (false == fabric_key.valid_key_id(FabricKeyId(id))) {
|
||||
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key),
|
||||
"Invalid 'id' attribute '%d'\n",
|
||||
|
@ -40,14 +38,25 @@ void read_xml_component_key(pugi::xml_node& xml_component_key,
|
|||
|
||||
VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id)));
|
||||
|
||||
fabric_key.set_key_name(FabricKeyId(id), name);
|
||||
fabric_key.set_key_value(FabricKeyId(id), value);
|
||||
|
||||
/* If we have an alias, set the value as well */
|
||||
const std::string& alias = get_attribute(xml_component_key, "alias", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
if (!alias.empty()) {
|
||||
fabric_key.set_key_alias(FabricKeyId(id), alias);
|
||||
}
|
||||
|
||||
/* If we have the alias set, name and valus are optional then
|
||||
* Otherwise, they are mandatory attributes
|
||||
*/
|
||||
pugiutil::ReqOpt required_name_value = pugiutil::ReqOpt::OPTIONAL;
|
||||
if (true == alias.empty()) {
|
||||
required_name_value = pugiutil::ReqOpt::REQUIRED;
|
||||
}
|
||||
|
||||
const std::string& name = get_attribute(xml_component_key, "name", loc_data, required_name_value).as_string();
|
||||
const size_t& value = get_attribute(xml_component_key, "value", loc_data, required_name_value).as_int();
|
||||
|
||||
fabric_key.set_key_name(FabricKeyId(id), name);
|
||||
fabric_key.set_key_value(FabricKeyId(id), value);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -40,7 +40,9 @@ int write_xml_fabric_component_key(std::fstream& fp,
|
|||
}
|
||||
|
||||
write_xml_attribute(fp, "id", size_t(component_key));
|
||||
write_xml_attribute(fp, "name", fabric_key.key_name(component_key).c_str());
|
||||
if (!fabric_key.key_name(component_key).empty()) {
|
||||
write_xml_attribute(fp, "name", fabric_key.key_name(component_key).c_str());
|
||||
}
|
||||
write_xml_attribute(fp, "value", fabric_key.key_value(component_key));
|
||||
|
||||
if (!fabric_key.key_alias(component_key).empty()) {
|
||||
|
|
|
@ -52,6 +52,10 @@ constexpr char* INV_PORT_POSTFIX = "_inv";
|
|||
/* Bitstream file strings */
|
||||
constexpr char* BITSTREAM_XML_FILE_NAME_POSTFIX = "_bitstream.xml";
|
||||
|
||||
constexpr char* DEFAULT_LB_DIR_NAME = "lb/";
|
||||
constexpr char* DEFAULT_RR_DIR_NAME = "routing/";
|
||||
constexpr char* DEFAULT_SUBMODULE_DIR_NAME = "sub_module/";
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -83,6 +83,12 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
|
|||
|
||||
VTR_LOG("\n");
|
||||
|
||||
/* Record the execution status in curr_status for each command
|
||||
* and summarize them in the final status
|
||||
*/
|
||||
int curr_status = CMD_EXEC_SUCCESS;
|
||||
int final_status = CMD_EXEC_SUCCESS;
|
||||
|
||||
/* Load fabric key from file */
|
||||
FabricKey predefined_fabric_key;
|
||||
if (true == cmd_context.option_enable(cmd, opt_load_fabric_key)) {
|
||||
|
@ -93,29 +99,38 @@ int build_fabric(OpenfpgaContext& openfpga_ctx,
|
|||
|
||||
VTR_LOG("\n");
|
||||
|
||||
openfpga_ctx.mutable_module_graph() = build_device_module_graph(openfpga_ctx.mutable_io_location_map(),
|
||||
openfpga_ctx.mutable_decoder_lib(),
|
||||
const_cast<const OpenfpgaContext&>(openfpga_ctx),
|
||||
g_vpr_ctx.device(),
|
||||
cmd_context.option_enable(cmd, opt_frame_view),
|
||||
cmd_context.option_enable(cmd, opt_compress_routing),
|
||||
cmd_context.option_enable(cmd, opt_duplicate_grid_pin),
|
||||
predefined_fabric_key,
|
||||
cmd_context.option_enable(cmd, opt_gen_random_fabric_key),
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
curr_status = build_device_module_graph(openfpga_ctx.mutable_module_graph(),
|
||||
openfpga_ctx.mutable_io_location_map(),
|
||||
openfpga_ctx.mutable_decoder_lib(),
|
||||
const_cast<const OpenfpgaContext&>(openfpga_ctx),
|
||||
g_vpr_ctx.device(),
|
||||
cmd_context.option_enable(cmd, opt_frame_view),
|
||||
cmd_context.option_enable(cmd, opt_compress_routing),
|
||||
cmd_context.option_enable(cmd, opt_duplicate_grid_pin),
|
||||
predefined_fabric_key,
|
||||
cmd_context.option_enable(cmd, opt_gen_random_fabric_key),
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
|
||||
/* If there is any error, final status cannot be overwritten by a success flag */
|
||||
if (CMD_EXEC_SUCCESS != curr_status) {
|
||||
final_status = curr_status;
|
||||
}
|
||||
|
||||
/* Output fabric key if user requested */
|
||||
if (true == cmd_context.option_enable(cmd, opt_write_fabric_key)) {
|
||||
std::string fkey_fname = cmd_context.option_value(cmd, opt_write_fabric_key);
|
||||
VTR_ASSERT(false == fkey_fname.empty());
|
||||
write_fabric_key_to_xml_file(openfpga_ctx.module_graph(),
|
||||
fkey_fname,
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
|
||||
curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(),
|
||||
fkey_fname,
|
||||
openfpga_ctx.arch().config_protocol.type(),
|
||||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
/* If there is any error, final status cannot be overwritten by a success flag */
|
||||
if (CMD_EXEC_SUCCESS != curr_status) {
|
||||
final_status = curr_status;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: should identify the error code from internal function execution */
|
||||
return CMD_EXEC_SUCCESS;
|
||||
return final_status;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -67,6 +67,7 @@ class OpenfpgaContext : public Context {
|
|||
const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; }
|
||||
const std::unordered_map<AtomNetId, t_net_power>& net_activity() const { return net_activity_; }
|
||||
const openfpga::NetlistManager& verilog_netlists() const { return verilog_netlists_; }
|
||||
const openfpga::NetlistManager& spice_netlists() const { return spice_netlists_; }
|
||||
public: /* Public mutators */
|
||||
openfpga::Arch& mutable_arch() { return arch_; }
|
||||
openfpga::SimulationSetting& mutable_simulation_setting() { return sim_setting_; }
|
||||
|
@ -86,6 +87,7 @@ class OpenfpgaContext : public Context {
|
|||
openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; }
|
||||
std::unordered_map<AtomNetId, t_net_power>& mutable_net_activity() { return net_activity_; }
|
||||
openfpga::NetlistManager& mutable_verilog_netlists() { return verilog_netlists_; }
|
||||
openfpga::NetlistManager& mutable_spice_netlists() { return spice_netlists_; }
|
||||
private: /* Internal data */
|
||||
/* Data structure to store information from read_openfpga_arch library */
|
||||
openfpga::Arch arch_;
|
||||
|
@ -130,6 +132,7 @@ class OpenfpgaContext : public Context {
|
|||
* TODO: Each format should have an independent entry
|
||||
*/
|
||||
openfpga::NetlistManager verilog_netlists_;
|
||||
openfpga::NetlistManager spice_netlists_;
|
||||
|
||||
/* Net activities of users' implementation */
|
||||
std::unordered_map<AtomNetId, t_net_power> net_activity_;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/********************************************************************
|
||||
* This file includes functions to compress the hierachy of routing architecture
|
||||
*******************************************************************/
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_time.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
#include "spice_api.h"
|
||||
#include "openfpga_spice.h"
|
||||
|
||||
/* Include global variables of VPR */
|
||||
#include "globals.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* A wrapper function to call the fabric SPICE generator of FPGA-SPICE
|
||||
*******************************************************************/
|
||||
int write_fabric_spice(OpenfpgaContext& openfpga_ctx,
|
||||
const Command& cmd, const CommandContext& cmd_context) {
|
||||
|
||||
CommandOptionId opt_output_dir = cmd.option("file");
|
||||
CommandOptionId opt_explicit_port_mapping = cmd.option("explicit_port_mapping");
|
||||
CommandOptionId opt_verbose = cmd.option("verbose");
|
||||
|
||||
/* This is an intermediate data structure which is designed to modularize the FPGA-SPICE
|
||||
* Keep it independent from any other outside data structures
|
||||
*/
|
||||
FabricSpiceOption options;
|
||||
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
|
||||
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));
|
||||
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
|
||||
options.set_compress_routing(openfpga_ctx.flow_manager().compress_routing());
|
||||
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
status = fpga_fabric_spice(openfpga_ctx.module_graph(),
|
||||
openfpga_ctx.mutable_spice_netlists(),
|
||||
openfpga_ctx.arch().tech_lib,
|
||||
options);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef OPENFPGA_SPICE_H
|
||||
#define OPENFPGA_SPICE_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "command.h"
|
||||
#include "command_context.h"
|
||||
#include "openfpga_context.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
int write_fabric_spice(OpenfpgaContext& openfpga_ctx,
|
||||
const Command& cmd, const CommandContext& cmd_context);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,78 @@
|
|||
/********************************************************************
|
||||
* Add commands to the OpenFPGA shell interface,
|
||||
* in purpose of generate SPICE netlists modeling the full FPGA fabric
|
||||
* This is one of the core engine of openfpga, including:
|
||||
* - generate_fabric_spice : generate Verilog netlists about FPGA fabric
|
||||
* - TODO: generate_spice_top_testbench : generate SPICE testbenches for top-level module
|
||||
* - TODO: generate_spice_grid_testbench : generate SPICE testbenches for grids
|
||||
* - TODO: generate_spice_cb_testbench : generate SPICE testbenches for connection blocks
|
||||
* - TODO: generate_spice_sb_testbench : generate SPICE testbenches for switch blocks
|
||||
* - TODO: generate_spice_lut_testbench : generate SPICE testbenches for Look-Up Tables
|
||||
* - TODO: generate_spice_hard_logic_testbench : generate SPICE testbenches for all the hard logics
|
||||
* - TODO: generate_spice_local_routing_testbench : generate SPICE testbenches for local routing
|
||||
* - TODO: generate_spice_cb_routing_testbench : generate SPICE testbenches for routing circuit inside connection blocks
|
||||
* - TODO: generate_spice_sb_routing_testbench : generate SPICE testbenches for routing circuit inside switch blocks
|
||||
*******************************************************************/
|
||||
#include "openfpga_spice.h"
|
||||
#include "openfpga_spice_command.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* - Add a command to Shell environment: generate fabric Verilog
|
||||
* - Add associated options
|
||||
* - Add command dependency
|
||||
*******************************************************************/
|
||||
static
|
||||
ShellCommandId add_openfpga_write_fabric_spice_command(openfpga::Shell<OpenfpgaContext>& shell,
|
||||
const ShellCommandClassId& cmd_class_id,
|
||||
const std::vector<ShellCommandId>& dependent_cmds) {
|
||||
Command shell_cmd("write_fabric_spice");
|
||||
|
||||
/* Add an option '--file' in short '-f'*/
|
||||
CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for SPICE netlists");
|
||||
shell_cmd.set_option_short_name(output_opt, "f");
|
||||
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--explicit_port_mapping' */
|
||||
shell_cmd.add_option("explicit_port_mapping", false, "Use explicit port mapping in Verilog netlists");
|
||||
|
||||
/* Add an option '--verbose' */
|
||||
shell_cmd.add_option("verbose", false, "Enable verbose output");
|
||||
|
||||
/* Add command 'write_fabric_spice' to the Shell */
|
||||
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SPICE netlists modeling full FPGA fabric");
|
||||
shell.set_command_class(shell_cmd_id, cmd_class_id);
|
||||
shell.set_command_execute_function(shell_cmd_id, write_fabric_spice);
|
||||
|
||||
/* Add command dependency to the Shell */
|
||||
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
|
||||
|
||||
return shell_cmd_id;
|
||||
}
|
||||
|
||||
void add_openfpga_spice_commands(openfpga::Shell<OpenfpgaContext>& shell) {
|
||||
/* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */
|
||||
const ShellCommandId& build_fabric_cmd_id = shell.command(std::string("build_fabric"));
|
||||
|
||||
/* Add a new class of commands */
|
||||
ShellCommandClassId openfpga_spice_cmd_class = shell.add_command_class("FPGA-SPICE");
|
||||
|
||||
/********************************
|
||||
* Command 'write_fabric_spice'
|
||||
*/
|
||||
/* The 'write_fabric_spice' command should NOT be executed before 'build_fabric' */
|
||||
std::vector<ShellCommandId> fabric_spice_dependent_cmds;
|
||||
fabric_spice_dependent_cmds.push_back(build_fabric_cmd_id);
|
||||
add_openfpga_write_fabric_spice_command(shell,
|
||||
openfpga_spice_cmd_class,
|
||||
fabric_spice_dependent_cmds);
|
||||
|
||||
/********************************
|
||||
* TODO: Command 'write_spice_top_testbench'
|
||||
*/
|
||||
/* The command 'write_spice_top_testbench' should NOT be executed before 'build_fabric' */
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef OPENFPGA_SPICE_COMMAND_H
|
||||
#define OPENFPGA_SPICE_COMMAND_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "shell.h"
|
||||
#include "openfpga_context.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void add_openfpga_spice_commands(openfpga::Shell<OpenfpgaContext>& shell);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -219,6 +219,10 @@ void build_mux_local_decoder_module(ModuleManager& module_manager,
|
|||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId module_id = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(module_id));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(module_id, ModuleManager::MODULE_CONFIG);
|
||||
|
||||
/* Add module ports */
|
||||
/* Add each input port */
|
||||
BasicPort addr_port(generate_mux_local_decoder_addr_port_name(), addr_size);
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#include "vtr_log.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
#include "build_essential_modules.h"
|
||||
#include "build_decoder_modules.h"
|
||||
#include "build_mux_modules.h"
|
||||
|
@ -26,20 +29,20 @@ namespace openfpga {
|
|||
* The main function to be called for building module graphs
|
||||
* for a FPGA fabric
|
||||
*******************************************************************/
|
||||
ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const DeviceContext& vpr_device_ctx,
|
||||
const bool& frame_view,
|
||||
const bool& compress_routing,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key,
|
||||
const bool& verbose) {
|
||||
int build_device_module_graph(ModuleManager& module_manager,
|
||||
IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const DeviceContext& vpr_device_ctx,
|
||||
const bool& frame_view,
|
||||
const bool& compress_routing,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key,
|
||||
const bool& verbose) {
|
||||
vtr::ScopedStartFinishTimer timer("Build fabric module graph");
|
||||
|
||||
/* Module manager to be built */
|
||||
ModuleManager module_manager;
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
CircuitModelId sram_model = openfpga_ctx.arch().config_protocol.memory_model();
|
||||
VTR_ASSERT(true == openfpga_ctx.arch().circuit_lib.valid_model_id(sram_model));
|
||||
|
@ -108,19 +111,23 @@ ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
|||
}
|
||||
|
||||
/* Build FPGA fabric top-level module */
|
||||
build_top_module(module_manager,
|
||||
io_location_map,
|
||||
decoder_lib,
|
||||
openfpga_ctx.arch().circuit_lib,
|
||||
vpr_device_ctx.grid,
|
||||
vpr_device_ctx.rr_graph,
|
||||
openfpga_ctx.device_rr_gsb(),
|
||||
openfpga_ctx.tile_direct(),
|
||||
openfpga_ctx.arch().arch_direct,
|
||||
openfpga_ctx.arch().config_protocol.type(),
|
||||
sram_model,
|
||||
frame_view, compress_routing, duplicate_grid_pin,
|
||||
fabric_key, generate_random_fabric_key);
|
||||
status = build_top_module(module_manager,
|
||||
io_location_map,
|
||||
decoder_lib,
|
||||
openfpga_ctx.arch().circuit_lib,
|
||||
vpr_device_ctx.grid,
|
||||
vpr_device_ctx.rr_graph,
|
||||
openfpga_ctx.device_rr_gsb(),
|
||||
openfpga_ctx.tile_direct(),
|
||||
openfpga_ctx.arch().arch_direct,
|
||||
openfpga_ctx.arch().config_protocol.type(),
|
||||
sram_model,
|
||||
frame_view, compress_routing, duplicate_grid_pin,
|
||||
fabric_key, generate_random_fabric_key);
|
||||
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Now a critical correction has to be done!
|
||||
* In the module construction, we always use prefix of ports because they are binded
|
||||
|
@ -131,7 +138,7 @@ ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
|||
*/
|
||||
rename_primitive_module_port_names(module_manager, openfpga_ctx.arch().circuit_lib);
|
||||
|
||||
return module_manager;
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -15,16 +15,17 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
ModuleManager build_device_module_graph(IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const DeviceContext& vpr_device_ctx,
|
||||
const bool& frame_view,
|
||||
const bool& compress_routing,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key,
|
||||
const bool& verbose);
|
||||
int build_device_module_graph(ModuleManager& module_manager,
|
||||
IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const OpenfpgaContext& openfpga_ctx,
|
||||
const DeviceContext& vpr_device_ctx,
|
||||
const bool& frame_view,
|
||||
const bool& compress_routing,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key,
|
||||
const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -215,6 +215,17 @@ void build_constant_generator_module(ModuleManager& module_manager,
|
|||
/* Add one output port */
|
||||
BasicPort const_output_port(generate_const_value_module_output_port_name(const_value), 1);
|
||||
module_manager.add_port(const_module, const_output_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
|
||||
/* Specify the usage of this module
|
||||
* 1: VDD
|
||||
* 0: GND
|
||||
*/
|
||||
if (1 == const_value) {
|
||||
module_manager.set_module_usage(const_module, ModuleManager::MODULE_VDD);
|
||||
} else {
|
||||
VTR_ASSERT(0 == const_value);
|
||||
module_manager.set_module_usage(const_module, ModuleManager::MODULE_VSS);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
|
|
@ -251,6 +251,9 @@ void build_primitive_block_module(ModuleManager& module_manager,
|
|||
/* Ensure that the module has been created and thus unique! */
|
||||
VTR_ASSERT(ModuleId::INVALID() != primitive_module);
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(primitive_module, ModuleManager::MODULE_GRID);
|
||||
|
||||
/* Note: to cooperate with the pb_type hierarchy and connections, we add the port of primitive pb_type here.
|
||||
* Since we have linked pb_type ports to circuit models when setting up FPGA-X2P,
|
||||
* no ports of the circuit model will be missing here
|
||||
|
@ -858,6 +861,9 @@ void rec_build_logical_tile_modules(ModuleManager& module_manager,
|
|||
ModuleId pb_module = module_manager.add_module(pb_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(pb_module));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(pb_module, ModuleManager::MODULE_GRID);
|
||||
|
||||
/* Add ports to the Verilog module */
|
||||
add_pb_type_ports_to_module_manager(module_manager, pb_module, physical_pb_type);
|
||||
|
||||
|
|
|
@ -82,6 +82,10 @@ void build_lut_module(ModuleManager& module_manager,
|
|||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId lut_module = module_manager.add_module(circuit_lib.model_name(lut_model));
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(lut_module));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(lut_module, ModuleManager::MODULE_LUT);
|
||||
|
||||
/* Add module ports */
|
||||
/* Add each global port */
|
||||
for (const auto& port : lut_global_ports) {
|
||||
|
|
|
@ -322,6 +322,9 @@ void build_memory_flatten_module(ModuleManager& module_manager,
|
|||
/* Create a module and add to the module manager */
|
||||
ModuleId mem_module = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG);
|
||||
|
||||
/* Add module ports */
|
||||
/* Input: BL port */
|
||||
|
@ -404,6 +407,9 @@ void build_memory_chain_module(ModuleManager& module_manager,
|
|||
/* Create a module and add to the module manager */
|
||||
ModuleId mem_module = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG);
|
||||
|
||||
/* Add an input port, which is the head of configuration chain in the module */
|
||||
/* TODO: restriction!!!
|
||||
|
@ -542,6 +548,9 @@ void build_frame_memory_module(ModuleManager& module_manager,
|
|||
ModuleId mem_module = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG);
|
||||
|
||||
/* Find the specification of the decoder:
|
||||
* Size of address port and data input
|
||||
*/
|
||||
|
|
|
@ -1145,6 +1145,15 @@ void build_cmos_mux_module(ModuleManager& module_manager,
|
|||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId mux_module = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(ModuleId::INVALID() != mux_module);
|
||||
|
||||
/* Label module usage */
|
||||
if (CIRCUIT_MODEL_MUX == circuit_lib.model_type(mux_model)) {
|
||||
module_manager.set_module_usage(mux_module, ModuleManager::MODULE_INTERC);
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(CIRCUIT_MODEL_LUT == circuit_lib.model_type(mux_model));
|
||||
module_manager.set_module_usage(mux_module, ModuleManager::MODULE_LUT);
|
||||
}
|
||||
|
||||
/* Add module ports */
|
||||
/* Add each input port
|
||||
* Treat MUX and LUT differently
|
||||
|
@ -1294,6 +1303,10 @@ void build_rram_mux_module(ModuleManager& module_manager,
|
|||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId module_id = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(ModuleId::INVALID() != module_id);
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(module_id, ModuleManager::MODULE_INTERC);
|
||||
|
||||
/* Add module ports */
|
||||
/* Add each global port */
|
||||
for (const auto& port : mux_global_ports) {
|
||||
|
|
|
@ -337,6 +337,9 @@ void build_switch_block_module(ModuleManager& module_manager,
|
|||
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
|
||||
ModuleId sb_module = module_manager.add_module(generate_switch_block_module_name(gsb_coordinate));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(sb_module, ModuleManager::MODULE_SB);
|
||||
|
||||
VTR_LOGV(verbose,
|
||||
"Building module '%s'...",
|
||||
generate_switch_block_module_name(gsb_coordinate).c_str());
|
||||
|
@ -736,6 +739,9 @@ void build_connection_block_module(ModuleManager& module_manager,
|
|||
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||
ModuleId cb_module = module_manager.add_module(generate_connection_block_module_name(cb_type, gsb_coordinate));
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(cb_module, ModuleManager::MODULE_CB);
|
||||
|
||||
VTR_LOGV(verbose,
|
||||
"Building module '%s'...",
|
||||
generate_connection_block_module_name(cb_type, gsb_coordinate).c_str());
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
/* Headers from vpr library */
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
#include "rr_gsb_utils.h"
|
||||
#include "openfpga_reserved_words.h"
|
||||
#include "openfpga_naming.h"
|
||||
|
@ -318,29 +321,34 @@ vtr::Matrix<size_t> add_top_module_connection_block_instances(ModuleManager& mod
|
|||
* 4. Add module nets to connect datapath ports
|
||||
* 5. Add module nets/submodules to connect configuration ports
|
||||
*******************************************************************/
|
||||
void build_top_module(ModuleManager& module_manager,
|
||||
IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const DeviceGrid& grids,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const TileDirect& tile_direct,
|
||||
const ArchDirect& arch_direct,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
const CircuitModelId& sram_model,
|
||||
const bool& frame_view,
|
||||
const bool& compact_routing_hierarchy,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key) {
|
||||
int build_top_module(ModuleManager& module_manager,
|
||||
IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const DeviceGrid& grids,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const TileDirect& tile_direct,
|
||||
const ArchDirect& arch_direct,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
const CircuitModelId& sram_model,
|
||||
const bool& frame_view,
|
||||
const bool& compact_routing_hierarchy,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Build FPGA fabric module");
|
||||
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
/* Create a module as the top-level fabric, and add it to the module manager */
|
||||
std::string top_module_name = generate_fpga_top_module_name();
|
||||
ModuleId top_module = module_manager.add_module(top_module_name);
|
||||
|
||||
/* Label module usage */
|
||||
module_manager.set_module_usage(top_module, ModuleManager::MODULE_TOP);
|
||||
|
||||
std::map<t_rr_type, vtr::Matrix<size_t>> cb_instance_ids;
|
||||
|
||||
/* Add sub modules, which are grid, SB and CBX/CBY modules as instances */
|
||||
|
@ -394,8 +402,11 @@ void build_top_module(ModuleManager& module_manager,
|
|||
compact_routing_hierarchy);
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(false == fabric_key.empty());
|
||||
load_top_module_memory_modules_from_fabric_key(module_manager, top_module,
|
||||
fabric_key);
|
||||
status = load_top_module_memory_modules_from_fabric_key(module_manager, top_module,
|
||||
fabric_key);
|
||||
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shuffle the configurable children in a random sequence */
|
||||
|
@ -432,6 +443,8 @@ void build_top_module(ModuleManager& module_manager,
|
|||
sram_orgz_type, circuit_lib.design_tech_type(sram_model),
|
||||
module_num_config_bits);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -25,22 +25,22 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void build_top_module(ModuleManager& module_manager,
|
||||
IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const DeviceGrid& grids,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const TileDirect& tile_direct,
|
||||
const ArchDirect& arch_direct,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
const CircuitModelId& sram_model,
|
||||
const bool& frame_view,
|
||||
const bool& compact_routing_hierarchy,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key);
|
||||
int build_top_module(ModuleManager& module_manager,
|
||||
IoLocationMap& io_location_map,
|
||||
DecoderLibrary& decoder_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const DeviceGrid& grids,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const TileDirect& tile_direct,
|
||||
const ArchDirect& arch_direct,
|
||||
const e_config_protocol_type& sram_orgz_type,
|
||||
const CircuitModelId& sram_model,
|
||||
const bool& frame_view,
|
||||
const bool& compact_routing_hierarchy,
|
||||
const bool& duplicate_grid_pin,
|
||||
const FabricKey& fabric_key,
|
||||
const bool& generate_random_fabric_key);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
/* Headers from vpr library */
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
#include "rr_gsb_utils.h"
|
||||
#include "openfpga_reserved_words.h"
|
||||
#include "openfpga_naming.h"
|
||||
|
@ -419,36 +422,47 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager
|
|||
module_manager.clear_configurable_children(top_module);
|
||||
|
||||
for (const FabricKeyId& key : fabric_key.keys()) {
|
||||
/* Find if the module name exist */
|
||||
ModuleId child_module = module_manager.find_module(fabric_key.key_name(key));
|
||||
if (false == module_manager.valid_module_id(child_module)) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Invalid key name '%s'!\n",
|
||||
fabric_key.key_name(key).c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find if instance id is valid */
|
||||
size_t child_instance = fabric_key.key_value(key);
|
||||
/* If we have alias, we try to find a instance in this name */
|
||||
std::pair<ModuleId, size_t> instance_info(ModuleId::INVALID(), 0);
|
||||
/* If we have an alias, we try to find a instance in this name */
|
||||
if (!fabric_key.key_alias(key).empty()) {
|
||||
child_instance = module_manager.instance_id(top_module, child_module, fabric_key.key_alias(key));
|
||||
/* Find the module id and instance id */
|
||||
instance_info = find_module_manager_instance_module_info(module_manager, top_module, fabric_key.key_alias(key));
|
||||
} else {
|
||||
/* If we do not have an alias, we use the name and value to build the info deck */
|
||||
instance_info.first = module_manager.find_module(fabric_key.key_name(key));
|
||||
instance_info.second = fabric_key.key_value(key);
|
||||
}
|
||||
|
||||
if (child_instance >= module_manager.num_instance(top_module, child_module)) {
|
||||
VTR_LOGF_ERROR(__FILE__, __LINE__,
|
||||
"Invalid key value '%ld'!\n",
|
||||
child_instance);
|
||||
return 1;
|
||||
if (false == module_manager.valid_module_id(instance_info.first)) {
|
||||
if (!fabric_key.key_alias(key).empty()) {
|
||||
VTR_LOG_ERROR("Invalid key alias '%s'!\n",
|
||||
fabric_key.key_alias(key).c_str());
|
||||
} else {
|
||||
VTR_LOG_ERROR("Invalid key name '%s'!\n",
|
||||
fabric_key.key_name(key).c_str());
|
||||
}
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (false == module_manager.valid_module_instance_id(top_module, instance_info.first, instance_info.second)) {
|
||||
if (!fabric_key.key_alias(key).empty()) {
|
||||
VTR_LOG_ERROR("Invalid key alias '%s'!\n",
|
||||
fabric_key.key_alias(key).c_str());
|
||||
} else {
|
||||
VTR_LOG_ERROR("Invalid key value '%ld'!\n",
|
||||
instance_info.second);
|
||||
}
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* Now we can add the child to configurable children of the top module */
|
||||
module_manager.add_configurable_child(top_module,
|
||||
child_module,
|
||||
child_instance);
|
||||
instance_info.first,
|
||||
instance_info.second);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace openfpga {
|
|||
***************************************************************************************/
|
||||
int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
|
||||
const std::string& fname,
|
||||
const e_config_protocol_type& config_protocol_type,
|
||||
const bool& verbose) {
|
||||
std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'");
|
||||
|
||||
|
@ -56,6 +57,14 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
|
|||
/* Build a fabric key database by visiting all the configurable children */
|
||||
FabricKey fabric_key;
|
||||
size_t num_keys = module_manager.configurable_children(top_module).size();
|
||||
|
||||
/* Exclude configuration-related modules in the keys */
|
||||
if (CONFIG_MEM_MEMORY_BANK == config_protocol_type) {
|
||||
num_keys -= 2;
|
||||
} else if (CONFIG_MEM_FRAME_BASED == config_protocol_type) {
|
||||
num_keys -= 1;
|
||||
}
|
||||
|
||||
fabric_key.reserve_keys(num_keys);
|
||||
|
||||
for (size_t ichild = 0; ichild < num_keys; ++ichild) {
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace openfpga {
|
|||
|
||||
int write_fabric_key_to_xml_file(const ModuleManager& module_manager,
|
||||
const std::string& fname,
|
||||
const e_config_protocol_type& config_protocol_type,
|
||||
const bool& verbose);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
|
|
@ -119,6 +119,12 @@ std::string ModuleManager::module_name(const ModuleId& module_id) const {
|
|||
return names_[module_id];
|
||||
}
|
||||
|
||||
ModuleManager::e_module_usage_type ModuleManager::module_usage(const ModuleId& module_id) const {
|
||||
/* Validate the module_id */
|
||||
VTR_ASSERT(valid_module_id(module_id));
|
||||
return usages_[module_id];
|
||||
}
|
||||
|
||||
/* Get the string of a module port type */
|
||||
std::string ModuleManager::module_port_type_str(const enum e_module_port_type& port_type) const {
|
||||
std::array<const char*, NUM_MODULE_PORT_TYPES> MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "GPIN PORTS", "GPOUT PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}};
|
||||
|
@ -469,6 +475,7 @@ ModuleId ModuleManager::add_module(const std::string& name) {
|
|||
|
||||
/* Allocate other attributes */
|
||||
names_.push_back(name);
|
||||
usages_.push_back(NUM_MODULE_USAGE_TYPES);
|
||||
parents_.emplace_back();
|
||||
children_.emplace_back();
|
||||
num_child_instances_.emplace_back();
|
||||
|
@ -553,6 +560,12 @@ void ModuleManager::set_module_name(const ModuleId& module, const std::string& n
|
|||
names_[module] = name;
|
||||
}
|
||||
|
||||
void ModuleManager::set_module_usage(const ModuleId& module, const e_module_usage_type& usage) {
|
||||
/* Validate the id of module */
|
||||
VTR_ASSERT( valid_module_id(module) );
|
||||
usages_[module] = usage;
|
||||
}
|
||||
|
||||
/* Set a port to be a wire */
|
||||
void ModuleManager::set_port_is_wire(const ModuleId& module, const std::string& port_name, const bool& is_wire) {
|
||||
/* Find the port */
|
||||
|
@ -879,6 +892,16 @@ bool ModuleManager::valid_module_net_id(const ModuleId& module, const ModuleNetI
|
|||
return ( size_t(net) < num_nets_[module] );
|
||||
}
|
||||
|
||||
bool ModuleManager::valid_module_instance_id(const ModuleId& parent_module,
|
||||
const ModuleId& child_module,
|
||||
const size_t& instance_id) const {
|
||||
if ( (false == valid_module_id(parent_module))
|
||||
|| (false == valid_module_id(child_module))) {
|
||||
return false;
|
||||
}
|
||||
return ( instance_id < num_instance(parent_module, child_module) );
|
||||
}
|
||||
|
||||
void ModuleManager::invalidate_name2id_map() {
|
||||
name_id_map_.clear();
|
||||
}
|
||||
|
|
|
@ -30,6 +30,10 @@ namespace openfpga {
|
|||
******************************************************************************/
|
||||
class ModuleManager {
|
||||
public: /* Private data structures */
|
||||
/* A type to indicate the usage of ports
|
||||
* Test bench generator use this to identify
|
||||
* what signals to drive
|
||||
*/
|
||||
enum e_module_port_type {
|
||||
MODULE_GLOBAL_PORT, /* Global inputs */
|
||||
MODULE_GPIN_PORT, /* General-purpose input */
|
||||
|
@ -38,10 +42,29 @@ class ModuleManager {
|
|||
MODULE_INOUT_PORT, /* Normal (non-global) inout ports */
|
||||
MODULE_INPUT_PORT, /* Normal (non-global) input ports */
|
||||
MODULE_OUTPUT_PORT, /* Normal (non-global) output ports */
|
||||
MODULE_CLOCK_PORT, /* Nromal (non-global) clock ports*/
|
||||
MODULE_CLOCK_PORT, /* Normal (non-global) clock ports*/
|
||||
NUM_MODULE_PORT_TYPES
|
||||
};
|
||||
|
||||
/* A type to indicate the usage of module
|
||||
* This helps FPGA-SPICE to identify which VDD/VSS
|
||||
* port should be applied to modules
|
||||
*/
|
||||
enum e_module_usage_type {
|
||||
MODULE_TOP, /* Top-level module */
|
||||
MODULE_CONFIG, /* Configuration modules, i.e., decoders, sram etc. */
|
||||
MODULE_INTERC, /* Programmable interconnection, e.g., routing multiplexer etc. */
|
||||
MODULE_GRID, /* Grids (programmable blocks) */
|
||||
MODULE_LUT, /* Look-Up Table (LUT) modules */
|
||||
MODULE_HARD_IP, /* Hard IP modules */
|
||||
MODULE_SB, /* Switch block modules */
|
||||
MODULE_CB, /* Connection block modules */
|
||||
MODULE_IO, /* I/O modules */
|
||||
MODULE_VDD, /* Local VDD lines to generate constant voltages */
|
||||
MODULE_VSS, /* Local VSS lines to generate constant voltages */
|
||||
NUM_MODULE_USAGE_TYPES
|
||||
};
|
||||
|
||||
public: /* Public Constructors */
|
||||
|
||||
public: /* Type implementations */
|
||||
|
@ -132,6 +155,7 @@ class ModuleManager {
|
|||
size_t num_modules() const;
|
||||
size_t num_nets(const ModuleId& module) const;
|
||||
std::string module_name(const ModuleId& module_id) const;
|
||||
e_module_usage_type module_usage(const ModuleId& module_id) const;
|
||||
std::string module_port_type_str(const enum e_module_port_type& port_type) const;
|
||||
std::vector<BasicPort> module_ports_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const;
|
||||
std::vector<ModulePortId> module_port_ids_by_type(const ModuleId& module_id, const enum e_module_port_type& port_type) const;
|
||||
|
@ -199,6 +223,8 @@ class ModuleManager {
|
|||
void set_module_port_name(const ModuleId& module, const ModulePortId& module_port, const std::string& port_name);
|
||||
/* Set a name for a module */
|
||||
void set_module_name(const ModuleId& module, const std::string& name);
|
||||
/* Set a usage for a module */
|
||||
void set_module_usage(const ModuleId& module, const e_module_usage_type& usage);
|
||||
/* Set a port to be a wire */
|
||||
void set_port_is_wire(const ModuleId& module, const std::string& port_name, const bool& is_wire);
|
||||
/* Set a port to be a register */
|
||||
|
@ -259,6 +285,9 @@ class ModuleManager {
|
|||
bool valid_module_id(const ModuleId& module) const;
|
||||
bool valid_module_port_id(const ModuleId& module, const ModulePortId& port) const;
|
||||
bool valid_module_net_id(const ModuleId& module, const ModuleNetId& net) const;
|
||||
bool valid_module_instance_id(const ModuleId& parent_module,
|
||||
const ModuleId& child_module,
|
||||
const size_t& instance_id) const;
|
||||
private: /* Private validators/invalidators */
|
||||
void invalidate_name2id_map();
|
||||
void invalidate_port_lookup();
|
||||
|
@ -266,7 +295,8 @@ class ModuleManager {
|
|||
private: /* Internal data */
|
||||
/* Module-level data */
|
||||
vtr::vector<ModuleId, ModuleId> ids_; /* Unique identifier for each Module */
|
||||
vtr::vector<ModuleId, std::string> names_; /* Unique identifier for each Module */
|
||||
vtr::vector<ModuleId, std::string> names_; /* Unique identifier for each Module */
|
||||
vtr::vector<ModuleId, e_module_usage_type> usages_; /* Usage of each module */
|
||||
vtr::vector<ModuleId, std::vector<ModuleId>> parents_; /* Parent modules that include the module */
|
||||
vtr::vector<ModuleId, std::vector<ModuleId>> children_; /* Child modules that this module contain */
|
||||
vtr::vector<ModuleId, std::vector<size_t>> num_child_instances_; /* Number of children instance in each child module */
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/******************************************************************************
|
||||
* Memember functions for data structure FabricSpiceOption
|
||||
******************************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
|
||||
#include "fabric_spice_options.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/**************************************************
|
||||
* Public Constructors
|
||||
*************************************************/
|
||||
FabricSpiceOption::FabricSpiceOption() {
|
||||
output_directory_.clear();
|
||||
explicit_port_mapping_ = false;
|
||||
compress_routing_ = false;
|
||||
verbose_output_ = false;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Public Accessors
|
||||
*************************************************/
|
||||
std::string FabricSpiceOption::output_directory() const {
|
||||
return output_directory_;
|
||||
}
|
||||
|
||||
bool FabricSpiceOption::explicit_port_mapping() const {
|
||||
return explicit_port_mapping_;
|
||||
}
|
||||
|
||||
bool FabricSpiceOption::compress_routing() const {
|
||||
return compress_routing_;
|
||||
}
|
||||
|
||||
bool FabricSpiceOption::verbose_output() const {
|
||||
return verbose_output_;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Private Mutators
|
||||
******************************************************************************/
|
||||
void FabricSpiceOption::set_output_directory(const std::string& output_dir) {
|
||||
output_directory_ = output_dir;
|
||||
}
|
||||
|
||||
void FabricSpiceOption::set_explicit_port_mapping(const bool& enabled) {
|
||||
explicit_port_mapping_ = enabled;
|
||||
}
|
||||
|
||||
void FabricSpiceOption::set_compress_routing(const bool& enabled) {
|
||||
compress_routing_ = enabled;
|
||||
}
|
||||
|
||||
void FabricSpiceOption::set_verbose_output(const bool& enabled) {
|
||||
verbose_output_ = enabled;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef FABRIC_SPICE_OPTIONS_H
|
||||
#define FABRIC_SPICE_OPTIONS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files required by the data structure definition
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
|
||||
/* Begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* Options for Fabric Spice generator
|
||||
*******************************************************************/
|
||||
class FabricSpiceOption {
|
||||
public: /* Public constructor */
|
||||
/* Set default options */
|
||||
FabricSpiceOption();
|
||||
public: /* Public accessors */
|
||||
std::string output_directory() const;
|
||||
bool explicit_port_mapping() const;
|
||||
bool compress_routing() const;
|
||||
bool verbose_output() const;
|
||||
public: /* Public mutators */
|
||||
void set_output_directory(const std::string& output_dir);
|
||||
void set_explicit_port_mapping(const bool& enabled);
|
||||
void set_compress_routing(const bool& enabled);
|
||||
void set_verbose_output(const bool& enabled);
|
||||
private: /* Internal Data */
|
||||
std::string output_directory_;
|
||||
bool explicit_port_mapping_;
|
||||
bool compress_routing_;
|
||||
bool verbose_output_;
|
||||
};
|
||||
|
||||
} /* End namespace openfpga*/
|
||||
|
||||
#endif
|
|
@ -0,0 +1,89 @@
|
|||
/********************************************************************
|
||||
* This file include top-level function of FPGA-SPICE
|
||||
********************************************************************/
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "openfpga_reserved_words.h"
|
||||
|
||||
#include "spice_constants.h"
|
||||
#include "spice_submodule.h"
|
||||
|
||||
/* Header file for this source file */
|
||||
#include "spice_api.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* A top-level function of FPGA-SPICE which focuses on fabric Spice generation
|
||||
* This function will generate
|
||||
* - primitive modules required by the full fabric
|
||||
* - which are LUTs, routing multiplexer, logic gates, transmission-gates etc.
|
||||
* - Routing modules, which are Switch Blocks (SBs) and Connection Blocks (CBs)
|
||||
* - Logic block modules, which are Configuration Logic Blocks (CLBs)
|
||||
* - FPGA module, which are the full FPGA fabric with configuration protocol
|
||||
*
|
||||
* Note:
|
||||
* - Please do NOT include ANY testbench generation in this function!!!
|
||||
* It is about the fabric itself, independent from any implementation
|
||||
* All the testbench generation should be in the function fpga_testbench_spice()
|
||||
********************************************************************/
|
||||
int fpga_fabric_spice(const ModuleManager& module_manager,
|
||||
NetlistManager& netlist_manager,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const FabricSpiceOption& options) {
|
||||
|
||||
vtr::ScopedStartFinishTimer timer("Write SPICE netlists for FPGA fabric\n");
|
||||
|
||||
std::string src_dir_path = format_dir_path(options.output_directory());
|
||||
|
||||
/* Create directories */
|
||||
create_directory(src_dir_path);
|
||||
|
||||
/* Sub directory under SRC directory to contain all the primitive block netlists */
|
||||
std::string submodule_dir_path = src_dir_path + std::string(DEFAULT_SUBMODULE_DIR_NAME);
|
||||
create_directory(submodule_dir_path);
|
||||
|
||||
/* Sub directory under SRC directory to contain all the logic block netlists */
|
||||
std::string lb_dir_path = src_dir_path + std::string(DEFAULT_LB_DIR_NAME);
|
||||
create_directory(lb_dir_path);
|
||||
|
||||
/* Sub directory under SRC directory to contain all the routing block netlists */
|
||||
std::string rr_dir_path = src_dir_path + std::string(DEFAULT_RR_DIR_NAME);
|
||||
create_directory(rr_dir_path);
|
||||
|
||||
/* Generate primitive Spice modules, which are corner stones of FPGA fabric
|
||||
* Note that this function MUST be called before Spice generation of
|
||||
* core logic (i.e., logic blocks and routing resources) !!!
|
||||
* This is because that this function will add the primitive Spice modules to
|
||||
* the module manager.
|
||||
* Without the modules in the module manager, core logic generation is not possible!!!
|
||||
*/
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
status = print_spice_submodule(netlist_manager,
|
||||
tech_lib,
|
||||
submodule_dir_path);
|
||||
|
||||
if (CMD_EXEC_SUCCESS != status) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Given a brief stats on how many Spice modules have been written to files */
|
||||
VTR_LOGV(options.verbose_output(),
|
||||
"Written %lu SPICE modules in total\n",
|
||||
module_manager.num_modules());
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef SPICE_API_H
|
||||
#define SPICE_API_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "netlist_manager.h"
|
||||
#include "module_manager.h"
|
||||
#include "technology_library.h"
|
||||
#include "fabric_spice_options.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
int fpga_fabric_spice(const ModuleManager& module_manager,
|
||||
NetlistManager& netlist_manager,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const FabricSpiceOption& options);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef SPICE_CONSTANTS_H
|
||||
#define SPICE_CONSTANTS_H
|
||||
|
||||
/* global parameters for dumping spice netlists */
|
||||
|
||||
constexpr char* SPICE_NETLIST_FILE_POSTFIX = ".sp";
|
||||
|
||||
constexpr char* TRANSISTOR_WRAPPER_POSTFIX = "_wrapper";
|
||||
|
||||
constexpr char* TRANSISTORS_SPICE_FILE_NAME = "transistor.sp";
|
||||
constexpr char* ESSENTIALS_SPICE_FILE_NAME = "inv_buf_passgate.sp";
|
||||
|
||||
#endif
|
|
@ -0,0 +1,113 @@
|
|||
/************************************************
|
||||
* This file includes functions on
|
||||
* outputting Verilog netlists for essential gates
|
||||
* which are inverters, buffers, transmission-gates
|
||||
* logic gates etc.
|
||||
***********************************************/
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
#include "spice_constants.h"
|
||||
#include "spice_essential_gates.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************
|
||||
* Print a SPICE model wrapper for a transistor model
|
||||
***********************************************/
|
||||
static
|
||||
int print_spice_transistor_model_wrapper(std::fstream& fp,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const TechnologyModelId& model) {
|
||||
|
||||
if (false == valid_file_stream(fp)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* Transistor model followed a fixed port mapping
|
||||
* [X|M]<MODEL_CARD_NAME> <DRAIN> <GATE> <SOURCE> <BULK>
|
||||
* which is a standard in SPICE modeling
|
||||
* We will output the pmos and nmos transistors wrappers
|
||||
* which are defined in this model
|
||||
*/
|
||||
for (int itype = TECH_LIB_TRANSISTOR_PMOS;
|
||||
itype < NUM_TECH_LIB_TRANSISTOR_TYPES;
|
||||
++itype) {
|
||||
const e_tech_lib_transistor_type& trans_type = static_cast<e_tech_lib_transistor_type>(itype);
|
||||
fp << ".subckt ";
|
||||
fp << tech_lib.transistor_model_name(model, trans_type) << TRANSISTOR_WRAPPER_POSTFIX;
|
||||
fp << " drain gate source bulk";
|
||||
fp << " L=" << std::setprecision(10) << tech_lib.transistor_model_chan_length(model, trans_type);
|
||||
fp << " W=" << std::setprecision(10) << tech_lib.transistor_model_min_width(model, trans_type);
|
||||
fp << "\n";
|
||||
|
||||
fp << tech_lib.model_ref(model);
|
||||
fp << "1";
|
||||
fp << " drain gate source bulk";
|
||||
fp << " " << tech_lib.transistor_model_name(model, trans_type);
|
||||
fp << " L=L W=W";
|
||||
fp << "\n";
|
||||
|
||||
fp << ".ends";
|
||||
fp << "\n";
|
||||
}
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Generate the SPICE netlist for transistors
|
||||
***********************************************/
|
||||
int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const std::string& submodule_dir) {
|
||||
std::string spice_fname = submodule_dir + std::string(TRANSISTORS_SPICE_FILE_NAME);
|
||||
|
||||
std::fstream fp;
|
||||
|
||||
/* Create the file stream */
|
||||
fp.open(spice_fname, std::fstream::out | std::fstream::trunc);
|
||||
/* Check if the file stream if valid or not */
|
||||
check_file_stream(spice_fname.c_str(), fp);
|
||||
|
||||
/* Create file */
|
||||
VTR_LOG("Generating SPICE netlist '%s' for transistor wrappers...",
|
||||
spice_fname.c_str());
|
||||
|
||||
/* Iterate over the transistor models */
|
||||
for (const TechnologyModelId& model : tech_lib.models()) {
|
||||
/* Focus on transistor model */
|
||||
if (TECH_LIB_MODEL_TRANSISTOR != tech_lib.model_type(model)) {
|
||||
continue;
|
||||
}
|
||||
/* Write a wrapper for the transistor model */
|
||||
if (CMD_EXEC_SUCCESS == print_spice_transistor_model_wrapper(fp, tech_lib, model)) {
|
||||
return CMD_EXEC_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close file handler*/
|
||||
fp.close();
|
||||
|
||||
/* Add fname to the netlist name list */
|
||||
NetlistId nlist_id = netlist_manager.add_netlist(spice_fname);
|
||||
VTR_ASSERT(NetlistId::INVALID() != nlist_id);
|
||||
netlist_manager.set_netlist_type(nlist_id, NetlistManager::SUBMODULE_NETLIST);
|
||||
|
||||
VTR_LOG("Done\n");
|
||||
|
||||
return CMD_EXEC_SUCCESS;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef SPICE_ESSENTIAL_GATES_H
|
||||
#define SPICE_ESSENTIAL_GATES_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <string>
|
||||
#include "netlist_manager.h"
|
||||
#include "technology_library.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
int print_spice_transistor_wrapper(NetlistManager& netlist_manager,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const std::string& submodule_dir);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
/*********************************************************************
|
||||
* This file includes top-level function to generate Spice primitive modules
|
||||
* and print them to files
|
||||
********************************************************************/
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from openfpgashell library */
|
||||
#include "command_exit_codes.h"
|
||||
|
||||
#include "spice_essential_gates.h"
|
||||
|
||||
#include "spice_constants.h"
|
||||
#include "spice_submodule.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/*********************************************************************
|
||||
* Top-level function to generate primitive modules:
|
||||
* 1. Transistor wrapper
|
||||
* 2. TODO: Logic gates: AND/OR, inverter, buffer and transmission-gate/pass-transistor
|
||||
* 3. TODO: Routing multiplexers
|
||||
* 4. TODO: Local encoders for routing multiplexers
|
||||
* 5. TODO: Wires
|
||||
* 6. TODO: Configuration memory blocks
|
||||
********************************************************************/
|
||||
int print_spice_submodule(NetlistManager& netlist_manager,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const std::string& submodule_dir) {
|
||||
|
||||
int status = CMD_EXEC_SUCCESS;
|
||||
|
||||
status = print_spice_transistor_wrapper(netlist_manager,
|
||||
tech_lib,
|
||||
submodule_dir);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef SPICE_SUBMODULE_H
|
||||
#define SPICE_SUBMODULE_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "netlist_manager.h"
|
||||
#include "technology_library.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
int print_spice_submodule(NetlistManager& netlist_manager,
|
||||
const TechnologyLibrary& tech_lib,
|
||||
const std::string& submodule_dir);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,152 @@
|
|||
/************************************************
|
||||
* Include functions for most frequently
|
||||
* used Spice writers
|
||||
***********************************************/
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "circuit_types.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
#include "spice_writer_utils.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/************************************************
|
||||
* Generate header comments for a Spice netlist
|
||||
* include the description
|
||||
***********************************************/
|
||||
void print_spice_file_header(std::fstream& fp,
|
||||
const std::string& usage) {
|
||||
VTR_ASSERT(true == valid_file_stream(fp));
|
||||
|
||||
auto end = std::chrono::system_clock::now();
|
||||
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
|
||||
|
||||
fp << "*********************************************" << std::endl;
|
||||
fp << "*\tFPGA-SPICE Netlist" << std::endl;
|
||||
fp << "*\tDescription: " << usage << std::endl;
|
||||
fp << "*\tAuthor: Xifan TANG" << std::endl;
|
||||
fp << "*\tOrganization: University of Utah" << std::endl;
|
||||
fp << "*\tDate: " << std::ctime(&end_time) ;
|
||||
fp << "*********************************************" << std::endl;
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Print Spice codes to include a netlist
|
||||
*******************************************************************/
|
||||
void print_spice_include_netlist(std::fstream& fp,
|
||||
const std::string& netlist_name) {
|
||||
VTR_ASSERT(true == valid_file_stream(fp));
|
||||
|
||||
fp << ".include \"" << netlist_name << "\"" << std::endl;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Print a Spice comment line
|
||||
***********************************************/
|
||||
void print_spice_comment(std::fstream& fp,
|
||||
const std::string& comment) {
|
||||
VTR_ASSERT(true == valid_file_stream(fp));
|
||||
|
||||
std::string comment_cover(comment.length() + 4, '*');
|
||||
fp << comment_cover << std::endl;
|
||||
fp << "* " << comment << " *" << std::endl;
|
||||
fp << comment_cover << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/************************************************
|
||||
* Generate a string for a port in SPICE format
|
||||
***********************************************/
|
||||
std::string generate_spice_port(const BasicPort& port) {
|
||||
VTR_ASSERT(1 == port.get_width());
|
||||
std::string ret = port.get_name();
|
||||
ret += "[";
|
||||
ret += std::to_string(port.get_lsb());
|
||||
ret += "]";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Print a SPICE subckt definition
|
||||
* We use the following format:
|
||||
* module <module_name> (<ports without directions>);
|
||||
***********************************************/
|
||||
void print_spice_subckt_definition(std::fstream& fp,
|
||||
const ModuleManager& module_manager, const ModuleId& module_id) {
|
||||
VTR_ASSERT(true == valid_file_stream(fp));
|
||||
|
||||
print_spice_comment(fp, std::string("SPICE module for " + module_manager.module_name(module_id)));
|
||||
|
||||
std::string module_head_line = ".subckt " + module_manager.module_name(module_id) + " ";
|
||||
fp << module_head_line;
|
||||
|
||||
/* Port sequence: global, inout, input, output and clock ports, */
|
||||
bool new_line = false;
|
||||
size_t pin_cnt = 0;
|
||||
for (int port_type = ModuleManager::MODULE_GLOBAL_PORT;
|
||||
port_type < ModuleManager::NUM_MODULE_PORT_TYPES;
|
||||
++port_type) {
|
||||
for (const auto& port : module_manager.module_ports_by_type(module_id, static_cast<ModuleManager::e_module_port_type>(port_type))) {
|
||||
ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name());
|
||||
VTR_ASSERT(ModulePortId::INVALID() != port_id);
|
||||
|
||||
/* Print port: only the port name is enough */
|
||||
for (const auto& pin : port.pins()) {
|
||||
|
||||
if (true == new_line) {
|
||||
std::string port_whitespace(module_head_line.length() - 2, ' ');
|
||||
fp << "+ " << port_whitespace;
|
||||
}
|
||||
|
||||
if (0 != pin_cnt) {
|
||||
write_space_to_file(fp, 1);
|
||||
}
|
||||
|
||||
BasicPort port_pin(port.get_name(), pin, pin);
|
||||
|
||||
fp << generate_spice_port(port_pin);
|
||||
|
||||
/* Increase the counter */
|
||||
pin_cnt++;
|
||||
|
||||
/* Currently we limit 10 ports per line to keep a clean netlist */
|
||||
new_line = false;
|
||||
if (10 == pin_cnt) {
|
||||
pin_cnt = 0;
|
||||
fp << std::endl;
|
||||
new_line = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/************************************************
|
||||
* Print an end line for a Spice module
|
||||
***********************************************/
|
||||
void print_spice_subckt_end(std::fstream& fp,
|
||||
const std::string& module_name) {
|
||||
VTR_ASSERT(true == valid_file_stream(fp));
|
||||
|
||||
fp << ".ends" << std::endl;
|
||||
print_spice_comment(fp, std::string("***** END SPICE module for " + module_name + " *****"));
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,52 @@
|
|||
/************************************************
|
||||
* Header file for spice_writer_utils.cpp
|
||||
* Include function declaration for most frequently
|
||||
* used Verilog writers
|
||||
***********************************************/
|
||||
#ifndef SPICE_WRITER_UTILS_H
|
||||
#define SPICE_WRITER_UTILS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "openfpga_port.h"
|
||||
#include "circuit_library.h"
|
||||
#include "module_manager.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/* Tips: for naming your function in this header/source file
|
||||
* If a function outputs to a file, its name should begin with "print_spice"
|
||||
* If a function creates a string without outputting to a file, its name should begin with "generate_spice"
|
||||
* Please show respect to this naming convention, in order to keep a clean header/source file
|
||||
* as well maintain a easy way to identify the functions
|
||||
*/
|
||||
|
||||
void print_spice_file_header(std::fstream& fp,
|
||||
const std::string& usage);
|
||||
|
||||
void print_spice_include_netlist(std::fstream& fp,
|
||||
const std::string& netlist_name);
|
||||
|
||||
void print_spice_comment(std::fstream& fp,
|
||||
const std::string& comment);
|
||||
|
||||
std::string generate_spice_port(const BasicPort& port);
|
||||
|
||||
void print_spice_subckt_definition(std::fstream& fp,
|
||||
const ModuleManager& module_manager, const ModuleId& module_id);
|
||||
|
||||
void print_spice_subckt_end(std::fstream& fp,
|
||||
const std::string& module_name);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -18,9 +18,6 @@ FabricVerilogOption::FabricVerilogOption() {
|
|||
include_timing_ = false;
|
||||
explicit_port_mapping_ = false;
|
||||
compress_routing_ = false;
|
||||
print_top_testbench_ = false;
|
||||
print_formal_verification_top_netlist_ = false;
|
||||
reference_verilog_file_path_.clear();
|
||||
print_user_defined_template_ = false;
|
||||
verbose_output_ = false;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,6 @@ class FabricVerilogOption {
|
|||
bool include_signal_init() const;
|
||||
bool explicit_port_mapping() const;
|
||||
bool compress_routing() const;
|
||||
bool print_top_testbench() const;
|
||||
bool print_formal_verification_top_netlist() const;
|
||||
bool print_autocheck_top_testbench() const;
|
||||
std::string reference_verilog_file_path() const;
|
||||
bool print_user_defined_template() const;
|
||||
bool verbose_output() const;
|
||||
public: /* Public mutators */
|
||||
|
@ -36,9 +32,6 @@ class FabricVerilogOption {
|
|||
void set_include_signal_init(const bool& enabled);
|
||||
void set_explicit_port_mapping(const bool& enabled);
|
||||
void set_compress_routing(const bool& enabled);
|
||||
void set_print_top_testbench(const bool& enabled);
|
||||
void set_print_formal_verification_top_netlist(const bool& enabled);
|
||||
void set_print_autocheck_top_testbench(const std::string& reference_verilog_file_path);
|
||||
void set_print_user_defined_template(const bool& enabled);
|
||||
void set_verbose_output(const bool& enabled);
|
||||
private: /* Internal Data */
|
||||
|
@ -48,10 +41,6 @@ class FabricVerilogOption {
|
|||
bool include_timing_;
|
||||
bool explicit_port_mapping_;
|
||||
bool compress_routing_;
|
||||
bool print_top_testbench_;
|
||||
bool print_formal_verification_top_netlist_;
|
||||
/* print_autocheck_top_testbench will be enabled when reference file path is not empty */
|
||||
std::string reference_verilog_file_path_;
|
||||
bool print_user_defined_template_;
|
||||
bool verbose_output_;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
#include "openfpga_reserved_words.h"
|
||||
|
||||
#include "device_rr_gsb.h"
|
||||
#include "verilog_constants.h"
|
||||
|
|
|
@ -13,9 +13,6 @@ constexpr char* INITIAL_SIMULATION_FLAG = "INITIAL_SIMULATION"; // the flag to e
|
|||
constexpr char* AUTOCHECKED_SIMULATION_FLAG = "AUTOCHECKED_SIMULATION"; // the flag to enable autochecked functional verification
|
||||
constexpr char* FORMAL_SIMULATION_FLAG = "FORMAL_SIMULATION"; // the flag to enable formal functional verification
|
||||
|
||||
constexpr char* DEFAULT_LB_DIR_NAME = "lb/";
|
||||
constexpr char* DEFAULT_RR_DIR_NAME = "routing/";
|
||||
constexpr char* DEFAULT_SUBMODULE_DIR_NAME = "sub_module/";
|
||||
constexpr char* MODELSIM_SIMULATION_TIME_UNIT = "ms";
|
||||
|
||||
// Icarus variables and flag
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "openfpga_setup_command.h"
|
||||
#include "openfpga_verilog_command.h"
|
||||
#include "openfpga_bitstream_command.h"
|
||||
#include "openfpga_spice_command.h"
|
||||
#include "openfpga_sdc_command.h"
|
||||
#include "basic_command.h"
|
||||
|
||||
|
@ -63,6 +64,9 @@ int main(int argc, char** argv) {
|
|||
/* Add openfpga bitstream commands */
|
||||
openfpga::add_openfpga_bitstream_commands(shell);
|
||||
|
||||
/* Add openfpga SPICE commands */
|
||||
openfpga::add_openfpga_spice_commands(shell);
|
||||
|
||||
/* Add openfpga sdc commands */
|
||||
openfpga::add_openfpga_sdc_commands(shell);
|
||||
|
||||
|
|
|
@ -93,6 +93,30 @@ size_t count_module_manager_module_configurable_children(const ModuleManager& mo
|
|||
return num_config_children;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Find the module id and instance id in module manager with a given instance name
|
||||
* This function will exhaustively search all the child module under a given parent
|
||||
* module
|
||||
******************************************************************************/
|
||||
std::pair<ModuleId, size_t> find_module_manager_instance_module_info(const ModuleManager& module_manager,
|
||||
const ModuleId& parent,
|
||||
const std::string& instance_name) {
|
||||
/* Deposit invalid values as default */
|
||||
std::pair<ModuleId, size_t> instance_info(ModuleId::INVALID(), 0);
|
||||
|
||||
/* Search all the child module and see we have a match */
|
||||
for (const ModuleId& child : module_manager.child_modules(parent)) {
|
||||
size_t child_instance = module_manager.instance_id(parent, child, instance_name);
|
||||
if (true == module_manager.valid_module_instance_id(parent, child, child_instance)) {
|
||||
instance_info.first = child;
|
||||
instance_info.second = child_instance;
|
||||
return instance_info;
|
||||
}
|
||||
}
|
||||
|
||||
return instance_info;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Add a module to the module manager based on the circuit-level
|
||||
* description of a circuit model
|
||||
|
@ -105,6 +129,26 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
|||
ModuleId module = module_manager.add_module(module_name);
|
||||
VTR_ASSERT(ModuleId::INVALID() != module);
|
||||
|
||||
/* Identify module usage based on circuit type:
|
||||
* LUT, SRAM, CCFF, I/O have specific usages
|
||||
* Others will be classified as hard IPs
|
||||
*/
|
||||
if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(circuit_model)) {
|
||||
module_manager.set_module_usage(module, ModuleManager::MODULE_LUT);
|
||||
} else if (CIRCUIT_MODEL_SRAM == circuit_lib.model_type(circuit_model)) {
|
||||
module_manager.set_module_usage(module, ModuleManager::MODULE_CONFIG);
|
||||
} else if (CIRCUIT_MODEL_CCFF == circuit_lib.model_type(circuit_model)) {
|
||||
module_manager.set_module_usage(module, ModuleManager::MODULE_CONFIG);
|
||||
} else if (CIRCUIT_MODEL_IOPAD == circuit_lib.model_type(circuit_model)) {
|
||||
module_manager.set_module_usage(module, ModuleManager::MODULE_IO);
|
||||
} else if (CIRCUIT_MODEL_WIRE == circuit_lib.model_type(circuit_model)) {
|
||||
module_manager.set_module_usage(module, ModuleManager::MODULE_INTERC);
|
||||
} else if (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(circuit_model)) {
|
||||
module_manager.set_module_usage(module, ModuleManager::MODULE_INTERC);
|
||||
} else {
|
||||
module_manager.set_module_usage(module, ModuleManager::MODULE_HARD_IP);
|
||||
}
|
||||
|
||||
/* Add ports */
|
||||
/* Find global ports and add one by one
|
||||
* Non-I/O Global input ports will be considered as global port to be shorted wired in the context of module manager
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
/* Headers from readarch library */
|
||||
#include "physical_types.h"
|
||||
|
@ -37,6 +38,10 @@ void reserve_module_manager_module_nets(ModuleManager& module_manager,
|
|||
size_t count_module_manager_module_configurable_children(const ModuleManager& module_manager,
|
||||
const ModuleId& module);
|
||||
|
||||
std::pair<ModuleId, size_t> find_module_manager_instance_module_info(const ModuleManager& module_manager,
|
||||
const ModuleId& parent,
|
||||
const std::string& instance_name);
|
||||
|
||||
ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model,
|
||||
const std::string& module_name);
|
||||
|
|
|
@ -32,5 +32,4 @@
|
|||
<key id="30" name="cbx_1__1_" value="0" alias="cbx_1__1_"/>
|
||||
<key id="31" name="grid_io_top" value="0" alias="grid_io_top_1_3"/>
|
||||
<key id="32" name="grid_io_left" value="1" alias="grid_io_left_0_2"/>
|
||||
<key id="33" name="decoder6to33" value="0"/>
|
||||
</fabric_key>
|
||||
|
|
Loading…
Reference in New Issue