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:
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s, [LINE%d])Invalid type for circuit model port(%s)!\n",
|
||||
__FILE__, __LINE__, circuit_lib.port_prefix(circuit_port));
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(File:%s, [LINE%d])Invalid type for circuit model port(%s)!\n",
|
||||
__FILE__, __LINE__, circuit_lib.port_prefix(circuit_port).c_str());
|
||||
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 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
|
||||
* 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)) {
|
||||
print_verilog_invbuf_module(fp, circuit_lib, circuit_model);
|
||||
continue;
|
||||
}
|
||||
if (SPICE_MODEL_PASSGATE == circuit_lib.model_type(circuit_model)) {
|
||||
print_verilog_passgate_module(fp, circuit_lib, circuit_model);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
if (SPICE_MODEL_GATE == spice_models[imodel].type) {
|
||||
dump_verilog_gate_module(fp, &(spice_models[imodel]));
|
||||
if (SPICE_MODEL_GATE == circuit_lib.model_type(circuit_model)) {
|
||||
print_verilog_gate_module(fp, circuit_lib, circuit_model);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
/* Initialize each input port */
|
||||
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;
|
||||
|
||||
/* Regular case: deposite initial signal values: a random value */
|
||||
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;
|
||||
|
|
|
@ -33,7 +33,7 @@ void print_verilog_file_header(std::fstream& fp,
|
|||
fp << "//\tFPGA Synthesizable Verilog Netlist" << std::endl;
|
||||
fp << "//\tDescription: " << usage << std::endl;
|
||||
fp << "//\tAuthor: Xifan TANG" << std::endl;
|
||||
fp << "//\t Organization: University of Utah" << std::endl;
|
||||
fp << "//\tOrganization: University of Utah" << std::endl;
|
||||
fp << "//\tDate: " << std::ctime(&end_time) ;
|
||||
fp << "//-------------------------------------------" << std::endl;
|
||||
fp << "//----- Time scale -----" << std::endl;
|
||||
|
@ -107,10 +107,10 @@ 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>
|
||||
*/
|
||||
if (VERILOG_PORT_CONKT == verilog_port_type) {
|
||||
verilog_line = port_info.get_name() + " " + size_str;
|
||||
verilog_line = port_info.get_name() + size_str;
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
|
||||
return verilog_line;
|
||||
|
|
Loading…
Reference in New Issue