[core] support last stage mux
This commit is contained in:
parent
b350889ab3
commit
47e30c3e4b
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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, std_cell_module_id, std_cell_instance_id,
|
||||
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());
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue