refactored gate verilog generation
This commit is contained in:
parent
b08ff465c9
commit
d8eb9866a0
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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*/
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue