refactored gate verilog generation

This commit is contained in:
tangxifan 2019-08-21 18:49:48 -06:00
parent b08ff465c9
commit d8eb9866a0
4 changed files with 236 additions and 11 deletions

View File

@ -234,8 +234,9 @@ t_port* find_pb_type_port_match_circuit_model_port(const t_pb_type* pb_type,
case SPICE_MODEL_PORT_SRAM: case SPICE_MODEL_PORT_SRAM:
break; break;
default: default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s, [LINE%d])Invalid type for circuit model port(%s)!\n", vpr_printf(TIO_MESSAGE_ERROR,
__FILE__, __LINE__, circuit_lib.port_prefix(circuit_port)); "(File:%s, [LINE%d])Invalid type for circuit model port(%s)!\n",
__FILE__, __LINE__, circuit_lib.port_prefix(circuit_port).c_str());
exit(1); exit(1);
} }
} }

View File

@ -331,6 +331,222 @@ void print_verilog_passgate_module(std::fstream& fp,
print_verilog_module_end(fp, circuit_lib.model_name(circuit_model)); print_verilog_module_end(fp, circuit_lib.model_name(circuit_model));
} }
/************************************************
* Print Verilog body codes of an N-input AND gate
***********************************************/
static
void print_verilog_and_or_gate_body(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const std::vector<CircuitPortId>& input_ports,
const std::vector<CircuitPortId>& output_ports) {
/* Ensure a valid file handler*/
check_file_handler(fp);
/* Find the logic operator for the gate */
std::string gate_verilog_operator;
switch (circuit_lib.gate_type(circuit_model)) {
case SPICE_MODEL_GATE_AND:
gate_verilog_operator = "&";
break;
case SPICE_MODEL_GATE_OR:
gate_verilog_operator = "|";
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,[LINE%d])Invalid topology for circuit model (name=%s)!\n",
__FILE__, __LINE__, circuit_lib.model_name(circuit_model).c_str());
exit(1);
}
/* Output verilog codes */
print_verilog_comment(fp, std::string("----- Verilog codes of a " + std::to_string(input_ports.size()) + "-input " + std::to_string(output_ports.size()) + "-output AND gate -----"));
for (const auto& output_port : output_ports) {
for (const auto& output_pin : circuit_lib.pins(output_port)) {
BasicPort output_port_info(circuit_lib.port_lib_name(output_port), output_pin, output_pin);
fp << "\tassign " << generate_verilog_port(VERILOG_PORT_CONKT, output_port_info);
fp << " = ";
size_t port_cnt = 0;
for (const auto& input_port : input_ports) {
for (const auto& input_pin : circuit_lib.pins(input_port)) {
/* Do not output AND/OR operator for the first element in the loop */
if (0 < port_cnt) {
fp << " " << gate_verilog_operator << " ";
}
BasicPort input_port_info(circuit_lib.port_lib_name(input_port), input_pin, input_pin);
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info);
/* Increment the counter for port */
port_cnt++;
}
}
fp << ";" << std::endl;
}
}
}
/************************************************
* Print Verilog body codes of an 2-input MUX gate
***********************************************/
static
void print_verilog_mux2_gate_body(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model,
const std::vector<CircuitPortId>& input_ports,
const std::vector<CircuitPortId>& output_ports) {
/* Ensure a valid file handler*/
check_file_handler(fp);
/* TODO: Move the check codes to check_circuit_library.cpp */
size_t num_err = 0;
/* Check on the port sequence and map */
/* MUX2 should only have 1 output port with size 1 */
if (1 != output_ports.size()) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d]) MUX2 circuit model (%s) must have only 1 output!\n",
__FILE__, __LINE__, circuit_lib.model_name(circuit_model).c_str());
num_err++;
}
for (const auto& output_port : output_ports) {
/* Bypass port size of 1 */
if (1 == circuit_lib.port_size(output_port)) {
continue;
}
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d]) Output port size of a MUX2 circuit model (%s) must be 1!\n",
__FILE__, __LINE__, circuit_lib.model_name(circuit_model).c_str());
num_err++;
}
/* MUX2 should only have 3 output port, each of which has a port size of 1 */
if (3 != input_ports.size()) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d]) MUX2 circuit model (%s) must have only 3 input!\n",
__FILE__, __LINE__, circuit_lib.model_name(circuit_model).c_str());
num_err++;
}
for (const auto& input_port : input_ports) {
/* Bypass port size of 1 */
if (1 == circuit_lib.port_size(input_port)) {
continue;
}
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d]) Input size MUX2 circuit model (%s) must be 1!\n",
__FILE__, __LINE__, circuit_lib.model_name(circuit_model).c_str());
num_err++;
}
if (0 < num_err) {
exit(1);
}
/* Now, we output the logic of MUX2
* IMPORTANT Restriction:
* We always assum the first two inputs are data inputs
* the third input is the select port
*/
fp << "\tassign ";
BasicPort out_port_info(circuit_lib.port_lib_name(output_ports[0]), 0, 0);
BasicPort sel_port_info(circuit_lib.port_lib_name(input_ports[2]), 0, 0);
BasicPort in0_port_info(circuit_lib.port_lib_name(input_ports[0]), 0, 0);
BasicPort in1_port_info(circuit_lib.port_lib_name(input_ports[1]), 0, 0);
fp << generate_verilog_port(VERILOG_PORT_CONKT, out_port_info);
fp << " = ";
fp << generate_verilog_port(VERILOG_PORT_CONKT, sel_port_info);
fp << " ? ";
fp << generate_verilog_port(VERILOG_PORT_CONKT, in0_port_info);
fp << " : ";
fp << generate_verilog_port(VERILOG_PORT_CONKT, in1_port_info);
fp << ";" << std::endl;
}
/************************************************
* Print a Verilog module of a logic gate
* which are standard cells
* Supported gate types:
* 1. N-input AND
* 2. N-input OR
* 3. 2-input MUX
***********************************************/
static
void print_verilog_gate_module(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
/* Ensure a valid file handler*/
check_file_handler(fp);
/* Find the input port, output port*/
std::vector<CircuitPortId> input_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT, true);
std::vector<CircuitPortId> output_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_OUTPUT, true);
std::vector<CircuitPortId> global_ports = circuit_lib.model_global_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT);
/* Make sure:
* There is only 1 output port,
* each size of which is 1
*/
VTR_ASSERT( (1 == output_ports.size()) && (1 == circuit_lib.port_size(output_ports[0])) );
/* Print Verilog module */
print_verilog_module_definition(fp, circuit_lib.model_name(circuit_model));
/* TODO: print global ports, this should be handled by ModuleManager */
for (const auto& port : global_ports) {
/* Configure each global port */
BasicPort basic_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
/* Print port */
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl;
}
for (const auto& input_port : input_ports) {
/* Configure each global port */
BasicPort basic_port(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port));
/* Print port */
fp << "\t" << generate_verilog_port(VERILOG_PORT_INPUT, basic_port) << "," << std::endl;
}
/* Configure each global port */
for (const auto& output_port : output_ports) {
BasicPort basic_port(circuit_lib.port_lib_name(output_port), circuit_lib.port_size(output_port));
/* Print port */
fp << "\t" << generate_verilog_port(VERILOG_PORT_OUTPUT, basic_port);
/* Last port does not need a comma */
if (output_port != output_ports.back()) {
fp << "," << std::endl;
} else {
fp << std::endl;
}
}
fp << ");" << std::endl;
/* Dump logics */
switch (circuit_lib.gate_type(circuit_model)) {
case SPICE_MODEL_GATE_AND:
case SPICE_MODEL_GATE_OR:
print_verilog_and_or_gate_body(fp, circuit_lib, circuit_model, input_ports, output_ports);
break;
case SPICE_MODEL_GATE_MUX2:
print_verilog_mux2_gate_body(fp, circuit_lib, circuit_model, input_ports, output_ports);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,[LINE%d])Invalid topology for circuit model (name=%s)!\n",
__FILE__, __LINE__, circuit_lib.model_name(circuit_model).c_str());
exit(1);
}
/* Print timing info */
print_verilog_submodule_timing(fp, circuit_lib, circuit_model);
/* Print signal initialization */
print_verilog_submodule_signal_init(fp, circuit_lib, circuit_model);
/* Put an end to the Verilog module */
print_verilog_module_end(fp, circuit_lib.model_name(circuit_model));
}
/************************************************ /************************************************
* Generate the Verilog netlist for essential gates * Generate the Verilog netlist for essential gates
* include inverters, buffers, transmission-gates, * include inverters, buffers, transmission-gates,
@ -365,15 +581,16 @@ void print_verilog_submodule_essentials(const std::string& verilog_dir,
} }
if (SPICE_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) { if (SPICE_MODEL_INVBUF == circuit_lib.model_type(circuit_model)) {
print_verilog_invbuf_module(fp, circuit_lib, circuit_model); print_verilog_invbuf_module(fp, circuit_lib, circuit_model);
continue;
} }
if (SPICE_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) { if (SPICE_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) {
print_verilog_passgate_module(fp, circuit_lib, circuit_model); print_verilog_passgate_module(fp, circuit_lib, circuit_model);
continue;
} }
/* if (SPICE_MODEL_GATE == circuit_lib.model_type(circuit_model)) {
if (SPICE_MODEL_GATE == spice_models[imodel].type) { print_verilog_gate_module(fp, circuit_lib, circuit_model);
dump_verilog_gate_module(fp, &(spice_models[imodel])); continue;
} }
*/
} }
/* Close file handler*/ /* Close file handler*/

View File

@ -95,13 +95,20 @@ void print_verilog_submodule_signal_init(std::fstream& fp,
/* Only for formal verification: deposite a zero signal values */ /* Only for formal verification: deposite a zero signal values */
/* Initialize each input port */ /* Initialize each input port */
for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) { for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) {
fp << "\t\t$deposit(" << circuit_lib.port_lib_name(input_port) << ", 1'b0);" << std::endl; BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port));
fp << "\t\t$deposit(";
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info);
fp << ", " << circuit_lib.port_size(input_port) << "'b" << std::string(circuit_lib.port_size(input_port), '0');
fp << ");" << std::endl;
} }
fp << "\t`else" << std::endl; fp << "\t`else" << std::endl;
/* Regular case: deposite initial signal values: a random value */ /* Regular case: deposite initial signal values: a random value */
for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) { for (const auto& input_port : circuit_lib.model_input_ports(circuit_model)) {
fp << "\t\t$deposit(" << circuit_lib.port_lib_name(input_port) << ", $random);" << std::endl; BasicPort input_port_info(circuit_lib.port_lib_name(input_port), circuit_lib.port_size(input_port));
fp << "\t\t$deposit(";
fp << generate_verilog_port(VERILOG_PORT_CONKT, input_port_info);
fp << ", $random);" << std::endl;
} }
fp << "\t`endif\n" << std::endl; fp << "\t`endif\n" << std::endl;

View File

@ -107,7 +107,7 @@ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_p
* others require a format of <port_type> [<lsb>:<msb>] <port_name> * others require a format of <port_type> [<lsb>:<msb>] <port_name>
*/ */
if (VERILOG_PORT_CONKT == verilog_port_type) { if (VERILOG_PORT_CONKT == verilog_port_type) {
verilog_line = port_info.get_name() + " " + size_str; verilog_line = port_info.get_name() + size_str;
} else { } else {
verilog_line = VERILOG_PORT_TYPE_STRING[verilog_port_type]; verilog_line = VERILOG_PORT_TYPE_STRING[verilog_port_type];
verilog_line += " " + size_str + " " + port_info.get_name(); verilog_line += " " + size_str + " " + port_info.get_name();