[core] support last stage mux

This commit is contained in:
tangxifan 2024-09-18 17:26:44 -07:00
parent b350889ab3
commit 47e30c3e4b
5 changed files with 175 additions and 11 deletions

View File

@ -259,6 +259,28 @@ CircuitModelId CircuitLibrary::pass_gate_logic_model(
return pgl_model_id;
}
/* Find the id of pass-gate circuit model
* Two cases to be considered:
* 1. this is a pass-gate circuit model, just find the data and return
* 2. this circuit model includes a pass-gate, find the link to pass-gate
* circuit model and go recursively
*/
CircuitModelId CircuitLibrary::last_stage_pass_gate_logic_model(
const CircuitModelId& model_id) const {
/* validate the model_id */
VTR_ASSERT(valid_model_id(model_id));
/* Return the data if this is a pass-gate circuit model */
if (CIRCUIT_MODEL_PASSGATE == model_type(model_id)) {
return model_ids_[model_id];
}
/* Otherwise, we need to make sure this circuit model contains a pass-gate */
CircuitModelId pgl_model_id = last_stage_pass_gate_logic_model_ids_[model_id];
VTR_ASSERT(CircuitModelId::INVALID() != pgl_model_id);
return pgl_model_id;
}
/* Find the name of pass-gate circuit model
* Two cases to be considered:
* 1. this is a pass-gate circuit model, just find the data and return
@ -279,6 +301,26 @@ std::string CircuitLibrary::pass_gate_logic_model_name(
return pass_gate_logic_model_names_[model_id];
}
/* Find the name of pass-gate circuit model
* Two cases to be considered:
* 1. this is a pass-gate circuit model, just find the data and return
* 2. this circuit model includes a pass-gate, find the link to pass-gate
* circuit model and go recursively
*/
std::string CircuitLibrary::last_stage_pass_gate_logic_model_name(
const CircuitModelId& model_id) const {
/* validate the model_id */
VTR_ASSERT(valid_model_id(model_id));
/* Return the data if this is a pass-gate circuit model */
if (CIRCUIT_MODEL_PASSGATE == model_type(model_id)) {
return model_names_[model_id];
}
/* Otherwise, we need to make sure this circuit model contains a pass-gate */
return last_stage_pass_gate_logic_model_names_[model_id];
}
/* Return the type of pass gate logic module, only applicable to circuit model
* whose type is pass-gate logic */
enum e_circuit_model_pass_gate_logic_type CircuitLibrary::pass_gate_logic_type(
@ -1262,6 +1304,8 @@ CircuitModelId CircuitLibrary::add_model(
/* Pass-gate-related parameters */
pass_gate_logic_model_names_.emplace_back();
pass_gate_logic_model_ids_.emplace_back(CircuitModelId::INVALID());
last_stage_pass_gate_logic_model_names_.emplace_back();
last_stage_pass_gate_logic_model_ids_.emplace_back(CircuitModelId::INVALID());
/* Delay information */
delay_types_.emplace_back();
@ -1485,6 +1529,15 @@ void CircuitLibrary::set_model_pass_gate_logic(const CircuitModelId& model_id,
return;
}
/* Set pass-gate logic information of a circuit model */
void CircuitLibrary::set_model_last_stage_pass_gate_logic(const CircuitModelId& model_id,
const std::string& model_name) {
/* validate the model_id */
VTR_ASSERT(valid_model_id(model_id));
last_stage_pass_gate_logic_model_names_[model_id] = model_name;
return;
}
/* Add a port to a circuit model */
CircuitPortId CircuitLibrary::add_model_port(
const CircuitModelId& model_id,
@ -2174,6 +2227,12 @@ void CircuitLibrary::link_pass_gate_logic_model(
}
pass_gate_logic_model_ids_[model_id] =
model(pass_gate_logic_model_names_[model_id]);
/* Get the circuit model id by name, skip those with empty names*/
if (true == last_stage_pass_gate_logic_model_names_[model_id].empty()) {
return;
}
last_stage_pass_gate_logic_model_ids_[model_id] =
model(last_stage_pass_gate_logic_model_names_[model_id]);
return;
}

View File

@ -272,6 +272,7 @@ class CircuitLibrary {
const CircuitModelId& model_id) const;
/* Pass-gate-logic information */
CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const;
CircuitModelId last_stage_pass_gate_logic_model(const CircuitModelId& model_id) const;
std::string pass_gate_logic_model_name(const CircuitModelId& model_id) const;
enum e_circuit_model_pass_gate_logic_type pass_gate_logic_type(
const CircuitModelId& model_id) const;
@ -448,6 +449,8 @@ class CircuitLibrary {
/* Pass-gate-related parameters */
void set_model_pass_gate_logic(const CircuitModelId& model_id,
const std::string& model_name);
void set_model_last_stage_pass_gate_logic(const CircuitModelId& model_id,
const std::string& model_name);
/* Port information */
CircuitPortId add_model_port(const CircuitModelId& model_id,
const enum e_circuit_model_port_type& port_type);
@ -664,6 +667,8 @@ class CircuitLibrary {
/* Pass-gate-related parameters */
vtr::vector<CircuitModelId, std::string> pass_gate_logic_model_names_;
vtr::vector<CircuitModelId, CircuitModelId> pass_gate_logic_model_ids_;
vtr::vector<CircuitModelId, std::string> last_stage_pass_gate_logic_model_names_;
vtr::vector<CircuitModelId, CircuitModelId> last_stage_pass_gate_logic_model_ids_;
/* Port information */
vtr::vector<CircuitPortId, CircuitPortId> port_ids_;

View File

@ -832,6 +832,20 @@ static void read_xml_circuit_model(pugi::xml_node& xml_model,
circuit_lib.set_model_pass_gate_logic(
model, get_attribute(xml_pass_gate_logic, "circuit_model_name", loc_data)
.as_string());
/* Last stage pass gate is optional */
size_t num_last_stage_pgl = count_children(xml_model, "last_stage_pass_gate_logic", loc_data, pugiutil::ReqOpt::OPTIONAL);
if (0 < num_last_stage_pgl) {
auto xml_last_stage_pass_gate_logic =
get_single_child(xml_model, "last_stage_pass_gate_logic", loc_data);
circuit_lib.set_model_last_stage_pass_gate_logic(
model, get_attribute(xml_last_stage_pass_gate_logic, "circuit_model_name", loc_data)
.as_string());
} else {
/* By default, assume the last stage circuit model is the same as others */
circuit_lib.set_model_last_stage_pass_gate_logic(
model, get_attribute(xml_pass_gate_logic, "circuit_model_name", loc_data)
.as_string());
}
}
/* Parse all the ports belonging to this circuit model

View File

@ -593,6 +593,13 @@ static void write_xml_circuit_model(std::fstream& fp, const char* fname,
circuit_lib.model_name(circuit_lib.pass_gate_logic_model(model)).c_str());
fp << "/>"
<< "\n";
fp << "\t\t\t"
<< "<last_stage_pass_gate_logic";
write_xml_attribute(
fp, "circuit_model_name",
circuit_lib.model_name(circuit_lib.last_stage_pass_gate_logic_model(model)).c_str());
fp << "/>"
<< "\n";
}
/* Write the ports of circuit model */

View File

@ -461,6 +461,7 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
/* We must have one */
VTR_ASSERT(ModuleId::INVALID() != std_cell_module_id);
/* Find the module ports of the standard cell MUX2 module */
std::vector<ModulePortId> std_cell_module_inputs;
std::vector<BasicPort> std_cell_module_input_ports;
@ -496,6 +497,61 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
module_manager.module_port(std_cell_module_id, std_cell_module_output);
VTR_ASSERT(1 == std_cell_module_output_port.get_width());
/* Find module information of the standard cell MUX2 */
CircuitModelId last_stage_std_cell_model = circuit_lib.model_last_stage_pass_gate_model(mux_model);
std::string last_stage_std_cell_module_name = circuit_lib.model_name(last_stage_std_cell_model);
/* Get the moduleId for the submodule */
ModuleId last_stage_std_cell_module_id =
module_manager.find_module(last_stage_std_cell_module_name);
/* We must have one */
VTR_ASSERT(ModuleId::INVALID() != last_stage_std_cell_module_id);
/* Find the input ports and output ports of the standard cell */
std::vector<CircuitPortId> last_stage_std_cell_input_ports =
circuit_lib.model_ports_by_type(last_stage_std_cell_model, CIRCUIT_MODEL_PORT_INPUT,
true);
std::vector<CircuitPortId> last_stage_std_cell_output_ports =
circuit_lib.model_ports_by_type(last_stage_std_cell_model, CIRCUIT_MODEL_PORT_OUTPUT,
true);
/* Quick check the requirements on port map */
VTR_ASSERT(3 == last_stage_std_cell_input_ports.size());
VTR_ASSERT(1 == last_stage_std_cell_output_ports.size());
/* Find the module ports of the standard cell MUX2 module */
std::vector<ModulePortId> last_stage_std_cell_module_inputs;
std::vector<BasicPort> last_stage_std_cell_module_input_ports;
/* Input 0 port is the first data path input of the tgate, whose size must be
* 1 ! */
for (size_t port_id = 0; port_id < 2; ++port_id) {
last_stage_std_cell_module_inputs.push_back(module_manager.find_module_port(
last_stage_std_cell_module_id,
circuit_lib.port_prefix(last_stage_std_cell_input_ports[port_id])));
VTR_ASSERT(true == module_manager.valid_module_port_id(
last_stage_std_cell_module_id, last_stage_std_cell_module_inputs[port_id]));
last_stage_std_cell_module_input_ports.push_back(module_manager.module_port(
last_stage_std_cell_module_id, last_stage_std_cell_module_inputs[port_id]));
VTR_ASSERT(1 == last_stage_std_cell_module_input_ports[port_id].get_width());
}
/* Mem port is the memory of the standard cell MUX2, whose size must be 1 ! */
ModulePortId last_stage_std_cell_module_mem = module_manager.find_module_port(
last_stage_std_cell_module_id, circuit_lib.port_prefix(last_stage_std_cell_input_ports[2]));
VTR_ASSERT(true == module_manager.valid_module_port_id(last_stage_std_cell_module_id,
last_stage_std_cell_module_mem));
BasicPort last_stage_std_cell_module_mem_port =
module_manager.module_port(last_stage_std_cell_module_id, last_stage_std_cell_module_mem);
VTR_ASSERT(1 == last_stage_std_cell_module_mem_port.get_width());
/* Output port is the data path output of the standard cell MUX2, whose size
* must be 1 ! */
ModulePortId last_stage_std_cell_module_output = module_manager.find_module_port(
last_stage_std_cell_module_id, circuit_lib.port_prefix(last_stage_std_cell_output_ports[0]));
VTR_ASSERT(true == module_manager.valid_module_port_id(
last_stage_std_cell_module_id, last_stage_std_cell_module_output));
BasicPort last_stage_std_cell_module_output_port =
module_manager.module_port(last_stage_std_cell_module_id, last_stage_std_cell_module_output);
VTR_ASSERT(1 == last_stage_std_cell_module_output_port.get_width());
/* Cache Net ids for each level of the multiplexer */
std::vector<std::vector<ModuleNetId>> module_nets_by_level;
module_nets_by_level.resize(mux_graph.num_node_levels());
@ -518,11 +574,17 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
/* To match the standard cell MUX2: We should have only 2 input_nodes */
VTR_ASSERT(2 == branch_size);
/* Last stage MUX model may have a different name */
ModuleId curr_stage_std_cell_module_id = std_cell_module_id;
if (true == mux_graph.is_node_output(node)) {
curr_stage_std_cell_module_id = last_stage_std_cell_module_id;
}
/* Find the instance id */
size_t std_cell_instance_id =
module_manager.num_instance(mux_module, std_cell_module_id);
module_manager.num_instance(mux_module, curr_stage_std_cell_module_id);
/* Add the module to mux_module */
module_manager.add_child_module(mux_module, std_cell_module_id);
module_manager.add_child_module(mux_module, curr_stage_std_cell_module_id);
/* Get the node level and index in the current level */
size_t output_node_level = mux_graph.node_level(node);
@ -530,7 +592,7 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
/* Set a name for the instance */
std::string std_cell_instance_name = generate_mux_branch_instance_name(
output_node_level, output_node_index_at_level, false);
module_manager.set_child_instance_name(mux_module, std_cell_module_id,
module_manager.set_child_instance_name(mux_module, curr_stage_std_cell_module_id,
std_cell_instance_id,
std_cell_instance_name);
@ -540,13 +602,16 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
/* This is an output node, we should use existing output nets */
MuxOutputId output_id = mux_graph.output_id(node);
branch_net = mux_module_output_nets[output_id];
module_manager.add_module_net_source(
mux_module, branch_net, curr_stage_std_cell_module_id, std_cell_instance_id,
last_stage_std_cell_module_output, last_stage_std_cell_module_output_port.get_lsb());
} else {
VTR_ASSERT(false == mux_graph.is_node_output(node));
branch_net = module_manager.create_module_net(mux_module);
module_manager.add_module_net_source(
mux_module, branch_net, curr_stage_std_cell_module_id, std_cell_instance_id,
std_cell_module_output, std_cell_module_output_port.get_lsb());
}
module_manager.add_module_net_source(
mux_module, branch_net, std_cell_module_id, std_cell_instance_id,
std_cell_module_output, std_cell_module_output_port.get_lsb());
/* Record the module net id in the cache */
module_nets_by_level[output_node_level][output_node_index_at_level] =
@ -567,10 +632,17 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
* Note that standard cell MUX2 only needs mem but NOT mem_inv
*/
for (const MuxMemId& mem : mems) {
module_manager.add_module_net_sink(
mux_module, mux_module_mem_nets[mem], std_cell_module_id,
std_cell_instance_id, std_cell_module_mem,
std_cell_module_mem_port.get_lsb());
if (true == mux_graph.is_node_output(node)) {
module_manager.add_module_net_sink(
mux_module, mux_module_mem_nets[mem], std_cell_module_id,
std_cell_instance_id, std_cell_module_mem,
std_cell_module_mem_port.get_lsb());
} else {
module_manager.add_module_net_sink(
mux_module, mux_module_mem_nets[mem], last_stage_std_cell_module_id,
last_stage_std_cell_instance_id, last_stage_std_cell_module_mem,
last_stage_std_cell_module_mem_port.get_lsb());
}
}
/* Wire the branch module inputs to the nets in previous stage */
@ -602,8 +674,15 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
mux_module, mux_module_input_nets[input_id], std_cell_module_id,
std_cell_instance_id, std_cell_module_inputs[node_id],
std_cell_module_input_ports[node_id].get_lsb());
} else if (true == mux_graph.is_node_output(node)) {
/* Find the input port of standard cell */
module_manager.add_module_net_sink(
mux_module,
module_nets_by_level[input_node_level][input_node_index_at_level],
last_stage_std_cell_module_id, std_cell_instance_id,
last_stage_std_cell_module_inputs[node_id],
last_stage_std_cell_module_input_ports[node_id].get_lsb());
} else {
VTR_ASSERT(false == mux_graph.is_node_input(input_nodes[node_id]));
/* Find the input port of standard cell */
module_manager.add_module_net_sink(
mux_module,