support wired LUT in FPGA-SPICE and FPGA-Verilog

This commit is contained in:
tangxifan 2018-11-15 15:57:49 -07:00
parent f7d7a056da
commit 861c449606
11 changed files with 352 additions and 22 deletions

Binary file not shown.

View File

@ -876,14 +876,28 @@ void set_one_pb_rr_node_default_prev_node_edge(t_rr_node* pb_rr_graph,
/* Mark the prev_edge and prev_node of all the rr_nodes in complex blocks */
static
void back_annotate_one_pb_rr_node_map_info_rec(t_pb* cur_pb) {
void back_annotate_one_pb_rr_node_map_info_rec(t_pb* cur_pb,
t_pb_graph_node* cur_pb_graph_node,
t_rr_node* pb_rr_nodes) {
int ipb, jpb, select_mode_index;
int iport, ipin, node_index;
t_rr_node* pb_rr_nodes = NULL;
t_pb_graph_node* child_pb_graph_node;
/* Return when we meet a null pb */
if (NULL == cur_pb) {
/* Skip non-LUT pb*/
if (LUT_CLASS != cur_pb_graph_node->pb_type->class_type) {
return;
}
for (iport = 0; iport < cur_pb_graph_node->num_output_ports; iport++) {
for (ipin = 0; ipin < cur_pb_graph_node->num_output_pins[iport]; ipin++) {
node_index = cur_pb_graph_node->output_pins[iport][ipin].pin_count_in_cluster;
if (OPEN != pb_rr_nodes[node_index].net_num) {
pb_rr_nodes[node_index].vpack_net_num = pb_rr_nodes[node_index].net_num;
}
}
}
return;
}
@ -971,7 +985,21 @@ void back_annotate_one_pb_rr_node_map_info_rec(t_pb* cur_pb) {
for (ipb = 0; ipb < cur_pb->pb_graph_node->pb_type->modes[select_mode_index].num_pb_type_children; ipb++) {
for (jpb = 0; jpb < cur_pb->pb_graph_node->pb_type->modes[select_mode_index].pb_type_children[ipb].num_pb; jpb++) {
if ((NULL != cur_pb->child_pbs[ipb])&&(NULL != cur_pb->child_pbs[ipb][jpb].name)) {
back_annotate_one_pb_rr_node_map_info_rec(&(cur_pb->child_pbs[ipb][jpb]));
back_annotate_one_pb_rr_node_map_info_rec(&(cur_pb->child_pbs[ipb][jpb]),
&(cur_pb->pb_graph_node->child_pb_graph_nodes[select_mode_index][ipb][jpb]),
cur_pb->rr_graph);
} else {
/* For wired LUT */
if (TRUE == is_pb_wired_lut(&(cur_pb->pb_graph_node->child_pb_graph_nodes[select_mode_index][ipb][jpb]),
&(cur_pb->pb_graph_node->pb_type->modes[select_mode_index].pb_type_children[ipb]),
cur_pb->rr_graph)) {
/* Reach here means that this LUT is in wired mode (a buffer)
* synchronize the net num
*/
back_annotate_one_pb_rr_node_map_info_rec(NULL,
&(cur_pb->pb_graph_node->child_pb_graph_nodes[select_mode_index][ipb][jpb]),
cur_pb->rr_graph);
}
}
}
}
@ -990,7 +1018,9 @@ void back_annotate_pb_rr_node_map_info() {
if (IO_TYPE == block[iblk].type) {
continue;
}
back_annotate_one_pb_rr_node_map_info_rec(block[iblk].pb);
back_annotate_one_pb_rr_node_map_info_rec(block[iblk].pb,
block[iblk].pb->pb_graph_node,
block[iblk].pb->rr_graph);
}
return;

View File

@ -37,3 +37,7 @@ enum e_pin2pin_interc_type {
extern char* renaming_report_postfix;
#define PRIMITIVE_WIRED_LUT -1
#define PRIMITIVE_IDLE 1
#define PRIMITIVE_NORMAL 0

View File

@ -5797,6 +5797,103 @@ void get_lut_logical_block_input_pin_vpack_net_num(t_logical_block* lut_logical_
return;
}
/* Find the vpack_net_num of the outputs of the logical_block */
void get_logical_block_output_vpack_net_num(t_logical_block* cur_logical_block,
int* num_lb_output_ports, int** num_lb_output_pins,
int*** lb_output_vpack_net_num) {
int iport, ipin;
int num_output_ports = 0;
int* num_output_pins = NULL;
t_model_ports* head = NULL;
int** output_vpack_net_num = NULL;
assert (NULL != cur_logical_block);
/* Count how many outputs we have */
head = cur_logical_block->model->outputs;
while (NULL != head) {
num_output_ports++;
head = head->next;
}
/* Allocate */
num_output_pins = (int*) my_calloc(num_output_ports, sizeof(int));
output_vpack_net_num = (int**) my_calloc(num_output_ports, sizeof(int*));
/* Fill the array */
iport = 0;
head = cur_logical_block->model->outputs;
while (NULL != head) {
num_output_pins[iport] = head->size;
output_vpack_net_num[iport] = (int*) my_calloc(num_output_pins[iport], sizeof(int));
/* Fill the array */
for (ipin = 0; ipin < num_output_pins[iport]; ipin++) {
output_vpack_net_num[iport][ipin] = cur_logical_block->output_nets[iport][ipin];
}
/* Go to the next */
head = head->next;
/* Update counter */
iport++;
}
assert (iport == num_output_ports);
/* Assign return values */
(*num_lb_output_ports) = num_output_ports;
(*num_lb_output_pins) = num_output_pins;
(*lb_output_vpack_net_num) = output_vpack_net_num;
return;
}
/* Adapt the truth from the actual connection from the input nets of a LUT,
*/
char** assign_post_routing_wired_lut_truth_table(t_logical_block* wired_lut_logical_block,
int lut_size, int* lut_pin_vpack_net_num,
int* truth_table_length) {
int inet, iport;
char** tt = (char**) my_malloc(sizeof(char*));
int num_lut_output_ports;
int* num_lut_output_pins;
int** lut_output_vpack_net_num;
/* The output of this mapped block is the wires routed through this LUT */
/* Find the vpack_net_num of the output of the lut_logical_block */
get_logical_block_output_vpack_net_num(wired_lut_logical_block,
&num_lut_output_ports,
&num_lut_output_pins,
&lut_output_vpack_net_num);
/* Check */
assert ( 1 == num_lut_output_ports);
assert ( 1 == num_lut_output_pins[0]);
assert ( OPEN != lut_output_vpack_net_num[0][0]);
/* truth_table_length will be always 1*/
(*truth_table_length) = 1;
/* Malloc */
tt[0] = (char*)my_malloc((lut_size + 3) * sizeof(char));
/* Fill the truth table !!! */
for (inet = 0; inet < lut_size; inet++) {
/* Find the vpack_num in the lut_input_pin, we fix it to be 1 */
if (lut_output_vpack_net_num[0][0] == lut_pin_vpack_net_num[inet]) {
tt[0][inet] = '1';
} else {
/* Otherwise it should be don't care */
tt[0][inet] = '-';
}
}
memcpy(tt[0] + lut_size, " 1", 3);
/* Free */
my_free(num_lut_output_pins);
for (iport = 0; iport < num_lut_output_ports; iport++) {
my_free(lut_output_vpack_net_num);
}
return tt;
}
/* Provide the truth table of a mapped logical block
* 1. Reorgainze the truth table to be consistent with the mapped nets of a LUT
@ -7480,5 +7577,47 @@ void rec_stats_spice_model_global_ports(t_spice_model* cur_spice_model,
return;
}
/* Identify if this child_pb is actually used for wiring!!! */
boolean is_pb_used_for_wiring(t_pb_graph_node* cur_pb_graph_node,
t_pb_type* cur_pb_type,
t_rr_node* pb_rr_graph) {
boolean is_used = FALSE;
int node_index;
int port_index = 0;
int iport, ipin;
for (iport = 0; iport < cur_pb_type->num_ports && !is_used; iport++) {
if (OUT_PORT == cur_pb_type->ports[iport].type) {
for (ipin = 0; ipin < cur_pb_type->ports[iport].num_pins; ipin++) {
node_index = cur_pb_graph_node->output_pins[port_index][ipin].pin_count_in_cluster;
if ((OPEN != pb_rr_graph[node_index].net_num)
|| (OPEN != pb_rr_graph[node_index].vpack_net_num)) {
return TRUE;
}
}
port_index++;
}
}
return is_used;
}
/* Identify if this is an unallocated pb that is used as a wired LUT */
boolean is_pb_wired_lut(t_pb_graph_node* cur_pb_graph_node,
t_pb_type* cur_pb_type,
t_rr_node* pb_rr_graph) {
boolean is_used = FALSE;
is_used = is_pb_used_for_wiring(cur_pb_graph_node,
cur_pb_type,
pb_rr_graph);
/* Return TRUE if this block is not used and it is a LUT ! */
if ((TRUE == is_used)
&& (LUT_CLASS == cur_pb_type->class_type)) {
return TRUE;
}
return FALSE;
}

View File

@ -457,6 +457,14 @@ char** assign_lut_truth_table(t_logical_block* mapped_logical_block,
void get_lut_logical_block_input_pin_vpack_net_num(t_logical_block* lut_logical_block,
int* num_lut_pin, int** lut_pin_net);
void get_logical_block_output_vpack_net_num(t_logical_block* cur_logical_block,
int* num_lb_output_ports, int** num_lb_output_pins,
int*** lb_output_vpack_net_num);
char** assign_post_routing_wired_lut_truth_table(t_logical_block* wired_lut_logical_block,
int lut_size, int* lut_pin_vpack_net_num,
int* truth_table_length);
char** assign_post_routing_lut_truth_table(t_logical_block* mapped_logical_block,
int lut_size, int* lut_pin_vpack_net_num,
int* truth_table_length);
@ -642,3 +650,11 @@ void get_mapped_lut_pb_input_pin_vpack_net_num(t_pb* lut_pb,
void rec_stats_spice_model_global_ports(t_spice_model* cur_spice_model,
boolean recursive,
t_llist** spice_model_head);
boolean is_pb_used_for_wiring(t_pb_graph_node* cur_pb_graph_node,
t_pb_type* cur_pb_type,
t_rr_node* pb_rr_graph);
boolean is_pb_wired_lut(t_pb_graph_node* cur_pb_graph_node,
t_pb_type* cur_pb_type,
t_rr_node* pb_rr_graph);

View File

@ -177,7 +177,8 @@ void fprint_pb_primitive_lut(FILE* fp,
t_logical_block* mapped_logical_block,
t_pb_graph_node* cur_pb_graph_node,
int index,
t_spice_model* spice_model) {
t_spice_model* spice_model,
int lut_status) {
int i;
int num_sram = 0;
int* sram_bits = NULL; /* decoded SRAM bits */
@ -217,7 +218,22 @@ void fprint_pb_primitive_lut(FILE* fp,
assert(SPICE_MODEL_LUT == spice_model->type);
/* Check if this is an idle logical block mapped*/
if (NULL != mapped_logical_block) {
switch (lut_status) {
case PRIMITIVE_WIRED_LUT:
/* Give a special truth table */
assert (VPACK_COMB == mapped_logical_block->type);
/* Get the mapped vpack_net_num of this physical LUT pb */
get_mapped_lut_pb_input_pin_vpack_net_num(prim_pb, &num_lut_pin_nets, &lut_pin_net);
/* consider LUT pin remapping when assign lut truth tables */
/* Match truth table and post-routing results */
truth_table = assign_post_routing_wired_lut_truth_table(mapped_logical_block,
num_lut_pin_nets, lut_pin_net, &truth_table_length);
break;
case PRIMITIVE_IDLE:
break;
case PRIMITIVE_NORMAL:
assert (NULL != mapped_logical_block);
/* Back-annotate to logical block */
/* Back-annotate to logical block */
mapped_logical_block->mapped_spice_model = spice_model;
mapped_logical_block->mapped_spice_model_index = spice_model->cnt;
@ -229,7 +245,12 @@ void fprint_pb_primitive_lut(FILE* fp,
/* Match truth table and post-routing results */
truth_table = assign_post_routing_lut_truth_table(mapped_logical_block,
num_lut_pin_nets, lut_pin_net, &truth_table_length);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, [LINE%d]) Invalid status(=%d) for LUT!\n",
__FILE__, __LINE__, lut_status);
exit(1);
}
/* Determine size of LUT*/
input_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);

View File

@ -15,4 +15,5 @@ void fprint_pb_primitive_lut(FILE* fp,
t_logical_block* mapped_logical_block,
t_pb_graph_node* cur_pb_graph_node,
int index,
t_spice_model* spice_model);
t_spice_model* spice_model,
int lut_status);

View File

@ -989,24 +989,47 @@ void fprint_pb_primitive_spice_model(FILE* fp,
/* Initialize */
prim_pb_type = prim_pb_graph_node->pb_type;
if (is_idle) {
switch (is_idle) {
case PRIMITIVE_WIRED_LUT:
mapped_logical_block = NULL;
} else {
break;
case PRIMITIVE_IDLE:
mapped_logical_block = NULL;
break;
case PRIMITIVE_NORMAL:
mapped_logical_block = &logical_block[prim_pb->logical_block];
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, [LINE%d]) Invalid ID(=%d) for primitive Verilog block!\n",
__FILE__, __LINE__, is_idle);
exit(1);
}
/* Asserts*/
assert(pb_index == prim_pb_graph_node->placement_index);
assert(0 == strcmp(spice_model->name, prim_pb_type->spice_model->name));
if (is_idle) {
switch (is_idle) {
case PRIMITIVE_WIRED_LUT:
assert(NULL == prim_pb);
} else {
break;
case PRIMITIVE_IDLE:
assert(NULL == prim_pb);
break;
case PRIMITIVE_NORMAL:
if (NULL == prim_pb) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb.\n",
__FILE__, __LINE__);
exit(1);
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, [LINE%d]) Invalid ID(=%d) for primitive Verilog block!\n",
__FILE__, __LINE__, is_idle);
exit(1);
}
/* According to different type, we print netlist*/
@ -1014,7 +1037,7 @@ void fprint_pb_primitive_spice_model(FILE* fp,
case SPICE_MODEL_LUT:
/* If this is a idle block we should set sram_bits to zero*/
fprint_pb_primitive_lut(fp, subckt_prefix, prim_pb, mapped_logical_block, prim_pb_graph_node,
pb_index, spice_model);
pb_index, spice_model, is_idle);
break;
case SPICE_MODEL_FF:
assert(NULL != spice_model->model_netlist);
@ -1234,6 +1257,17 @@ void fprint_spice_pb_graph_node_rec(FILE* fp,
exit(1);
}
cur_pb_type = cur_pb_graph_node->pb_type;
/* For wired LUTs only */
if (NULL == cur_pb) {
assert(NULL != cur_pb_type->spice_model);
assert (LUT_CLASS == cur_pb_type->class_type);
fprint_pb_primitive_spice_model(fp, formatted_subckt_prefix,
NULL, cur_pb_graph_node,
pb_type_index, cur_pb_type->spice_model, PRIMITIVE_WIRED_LUT);
return;
}
mode_index = cur_pb->mode;
/* Recursively finish all the child pb_types*/
@ -1254,6 +1288,16 @@ void fprint_spice_pb_graph_node_rec(FILE* fp,
if ((NULL != cur_pb->child_pbs[ipb])&&(NULL != cur_pb->child_pbs[ipb][jpb].name)) {
fprint_spice_pb_graph_node_rec(fp, pass_on_prefix, &(cur_pb->child_pbs[ipb][jpb]),
cur_pb->child_pbs[ipb][jpb].pb_graph_node, jpb);
/* For wired LUT */
} else if (TRUE == is_pb_wired_lut(&(cur_pb->pb_graph_node->child_pb_graph_nodes[mode_index][ipb][jpb]),
&(cur_pb->pb_graph_node->pb_type->modes[mode_index].pb_type_children[ipb]),
cur_pb->rr_graph)) {
/* Reach here means that this LUT is in wired mode (a buffer)
* Print the Verilog of wired LUTs
*/
fprint_spice_pb_graph_node_rec(fp, pass_on_prefix, NULL,
&(cur_pb->pb_graph_node->child_pb_graph_nodes[mode_index][ipb][jpb]),
jpb);
} else {
/* Check if this pb has no children, no children mean idle*/
fprint_spice_idle_pb_graph_node_rec(fp, pass_on_prefix,

View File

@ -39,7 +39,8 @@ void dump_verilog_pb_primitive_lut(FILE* fp,
t_logical_block* mapped_logical_block,
t_pb_graph_node* cur_pb_graph_node,
int index,
t_spice_model* verilog_model) {
t_spice_model* verilog_model,
int lut_status) {
int i;
int* sram_bits = NULL; /* decoded SRAM bits */
int truth_table_length = 0;
@ -95,7 +96,21 @@ void dump_verilog_pb_primitive_lut(FILE* fp,
assert(SPICE_MODEL_LUT == verilog_model->type);
/* Check if this is an idle logical block mapped*/
if (NULL != mapped_logical_block) {
switch (lut_status) {
case PRIMITIVE_WIRED_LUT:
/* Give a special truth table */
assert (VPACK_COMB == mapped_logical_block->type);
/* Get the mapped vpack_net_num of this physical LUT pb */
get_mapped_lut_pb_input_pin_vpack_net_num(prim_pb, &num_lut_pin_nets, &lut_pin_net);
/* consider LUT pin remapping when assign lut truth tables */
/* Match truth table and post-routing results */
truth_table = assign_post_routing_wired_lut_truth_table(mapped_logical_block,
num_lut_pin_nets, lut_pin_net, &truth_table_length);
break;
case PRIMITIVE_IDLE:
break;
case PRIMITIVE_NORMAL:
assert (NULL != mapped_logical_block);
/* Back-annotate to logical block */
mapped_logical_block->mapped_spice_model = verilog_model;
mapped_logical_block->mapped_spice_model_index = verilog_model->cnt;
@ -107,7 +122,14 @@ void dump_verilog_pb_primitive_lut(FILE* fp,
/* Match truth table and post-routing results */
truth_table = assign_post_routing_lut_truth_table(mapped_logical_block,
num_lut_pin_nets, lut_pin_net, &truth_table_length);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, [LINE%d]) Invalid status(=%d) for LUT!\n",
__FILE__, __LINE__, lut_status);
exit(1);
}
/* Determine size of LUT*/
input_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
output_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);

View File

@ -5,4 +5,5 @@ void dump_verilog_pb_primitive_lut(FILE* fp,
t_logical_block* mapped_logical_block,
t_pb_graph_node* cur_pb_graph_node,
int index,
t_spice_model* spice_model);
t_spice_model* spice_model,
int lut_status);

View File

@ -1598,23 +1598,46 @@ void dump_verilog_pb_primitive_verilog_model(FILE* fp,
/* Initialize */
prim_pb_type = prim_pb_graph_node->pb_type;
if (is_idle) {
switch (is_idle) {
case PRIMITIVE_WIRED_LUT:
mapped_logical_block = NULL;
} else {
break;
case PRIMITIVE_IDLE:
mapped_logical_block = NULL;
break;
case PRIMITIVE_NORMAL:
mapped_logical_block = &logical_block[prim_pb->logical_block];
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, [LINE%d]) Invalid ID(=%d) for primitive Verilog block!\n",
__FILE__, __LINE__, is_idle);
exit(1);
}
/* Asserts*/
assert(pb_index == prim_pb_graph_node->placement_index);
assert(0 == strcmp(verilog_model->name, prim_pb_type->spice_model->name));
if (is_idle) {
switch (is_idle) {
case PRIMITIVE_WIRED_LUT:
assert(NULL == prim_pb);
} else {
break;
case PRIMITIVE_IDLE:
assert(NULL == prim_pb);
break;
case PRIMITIVE_NORMAL:
if (NULL == prim_pb) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb.\n",
__FILE__, __LINE__);
exit(1);
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, [LINE%d]) Invalid ID(=%d) for primitive Verilog block!\n",
__FILE__, __LINE__, is_idle);
exit(1);
}
/* According to different type, we print netlist*/
@ -1622,7 +1645,7 @@ void dump_verilog_pb_primitive_verilog_model(FILE* fp,
case SPICE_MODEL_LUT:
/* If this is a idle block we should set sram_bits to zero*/
dump_verilog_pb_primitive_lut(fp, subckt_prefix, prim_pb, mapped_logical_block, prim_pb_graph_node,
pb_index, verilog_model);
pb_index, verilog_model, is_idle);
break;
case SPICE_MODEL_FF:
assert(NULL != verilog_model->model_netlist);
@ -1960,6 +1983,25 @@ void dump_verilog_pb_graph_node_rec(FILE* fp,
exit(1);
}
cur_pb_type = cur_pb_graph_node->pb_type;
/* For wired LUTs only */
if (NULL == cur_pb) {
assert(NULL != cur_pb_type->spice_model);
assert (LUT_CLASS == cur_pb_type->class_type);
dump_verilog_pb_primitive_verilog_model(fp, formatted_subckt_prefix,
NULL, cur_pb_graph_node,
pb_type_index, cur_pb_type->spice_model, PRIMITIVE_WIRED_LUT);
/* update the number of SRAM, I/O pads */
/* update stamped iopad counter */
stamped_iopad_cnt += cur_pb->num_iopads;
/* update stamped sram counter */
stamped_sram_cnt += cur_pb->num_conf_bits;
/* Check */
assert(stamped_sram_cnt == get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info));
assert(stamped_iopad_cnt == iopad_verilog_model->cnt);
return;
}
mode_index = cur_pb->mode;
/* Recursively finish all the child pb_types*/
@ -1980,6 +2022,16 @@ void dump_verilog_pb_graph_node_rec(FILE* fp,
if ((NULL != cur_pb->child_pbs[ipb])&&(NULL != cur_pb->child_pbs[ipb][jpb].name)) {
dump_verilog_pb_graph_node_rec(fp, pass_on_prefix, &(cur_pb->child_pbs[ipb][jpb]),
cur_pb->child_pbs[ipb][jpb].pb_graph_node, jpb);
/* For wired LUT */
} else if (TRUE == is_pb_wired_lut(&(cur_pb->pb_graph_node->child_pb_graph_nodes[mode_index][ipb][jpb]),
&(cur_pb->pb_graph_node->pb_type->modes[mode_index].pb_type_children[ipb]),
cur_pb->rr_graph)) {
/* Reach here means that this LUT is in wired mode (a buffer)
* Print the Verilog of wired LUTs
*/
dump_verilog_pb_graph_node_rec(fp, pass_on_prefix, NULL,
&(cur_pb->pb_graph_node->child_pb_graph_nodes[mode_index][ipb][jpb]),
jpb);
} else {
/* Check if this pb has no children, no children mean idle*/
dump_verilog_idle_pb_graph_node_rec(fp, pass_on_prefix,