/***********************************/ /* SPICE Modeling for VPR */ /* Xifan TANG, EPFL/LSI */ /***********************************/ #include #include #include #include #include #include #include #include /* Include vpr structs*/ #include "util.h" #include "physical_types.h" #include "vpr_types.h" #include "globals.h" #include "rr_graph.h" #include "rr_graph_swseg.h" #include "route_common.h" #include "vpr_utils.h" /* Include spice support headers*/ #include "linkedlist.h" #include "fpga_x2p_types.h" #include "fpga_x2p_utils.h" #include "fpga_x2p_pbtypes_utils.h" #include "fpga_x2p_bitstream_utils.h" #include "fpga_x2p_globals.h" /* Include verilog support headers*/ #include "verilog_global.h" #include "verilog_utils.h" #include "verilog_pbtypes.h" #include "verilog_primitives.h" /* Subroutines */ /* Dump a hard logic primitive node * This primitive can be a FF or a hard_logic, or an iopad */ void dump_verilog_pb_generic_primitive(t_sram_orgz_info* cur_sram_orgz_info, FILE* fp, char* subckt_prefix, t_pb_graph_node* prim_pb_graph_node, int index, t_spice_model* verilog_model) { int num_pad_port = 0; /* INOUT port */ t_spice_model_port** pad_ports = NULL; int num_input_port = 0; t_spice_model_port** input_ports = NULL; int num_output_port = 0; t_spice_model_port** output_ports = NULL; int num_clock_port = 0; t_spice_model_port** clock_ports = NULL; int num_sram_port = 0; t_spice_model_port** sram_ports = NULL; int num_sram = 0; /* int* sram_bits = NULL; */ char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/ t_pb_type* prim_pb_type = NULL; char* port_prefix = NULL; /* For each SRAM, we could have multiple BLs/WLs */ int num_bl_ports = 0; t_spice_model_port** bl_port = NULL; int num_wl_ports = 0; t_spice_model_port** wl_port = NULL; int cur_num_sram = 0; int num_conf_bits = 0; int num_reserved_conf_bits = 0; t_spice_model* mem_model = NULL; int cur_bl, cur_wl; char* mem_subckt_name = NULL; /* Ensure a valid file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n", __FILE__, __LINE__); exit(1); } /* Ensure a valid pb_graph_node */ if (NULL == prim_pb_graph_node) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n", __FILE__, __LINE__); exit(1); } /* Find ports*/ pad_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INOUT, &num_pad_port, TRUE); 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); clock_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_CLOCK, &num_clock_port, TRUE); sram_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE); /* Asserts */ assert((SPICE_MODEL_IOPAD == verilog_model->type) /* Support IO PAD which matches the physical design */ || (SPICE_MODEL_FF == verilog_model->type) /* Support IO PAD which matches the physical design */ || (SPICE_MODEL_HARDLOGIC == verilog_model->type)); /* Support IO PAD which matches the physical design */ /* Initialize */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); prim_pb_type = prim_pb_graph_node->pb_type; /* Generate Subckt for pb_type*/ /* Simplify the port prefix, make SPICE netlist readable */ port_prefix = (char*)my_malloc(sizeof(char)* (strlen(prim_pb_type->name) + 1)); sprintf(port_prefix, "%s", prim_pb_type->name); /* Print Comment lines depends on the type of this SPICE model */ fprintf(fp, "//----- %s Verilog module: %s%s -----\n", generate_string_spice_model_type(verilog_model->type), formatted_subckt_prefix, port_prefix); /* Definition line */ fprintf(fp, "module %s%s (", formatted_subckt_prefix, port_prefix); fprintf(fp, "\n"); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE, FALSE)) { fprintf(fp, ",\n"); } /* TODO: assert this is physical mode */ num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1); /* Get current counter of mem_bits, bl and wl */ cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &cur_bl, &cur_wl); /* print ports --> input ports */ dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, TRUE, FALSE, FALSE); /* IOPADs requires a specical port to output */ if (SPICE_MODEL_IOPAD == verilog_model->type) { fprintf(fp, ",\n"); /* Print output port */ fprintf(fp, "inout [%d:%d] %s%s\n", verilog_model->cnt, verilog_model->cnt, gio_inout_prefix, verilog_model->prefix); } /* Print SRAM ports */ /* connect to reserved BL/WLs ? */ num_reserved_conf_bits = count_num_reserved_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0); /* Get the number of configuration bits required by this MUX */ num_conf_bits = count_num_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0); /* Reserved sram ports */ if (0 < num_reserved_conf_bits) { fprintf(fp, ",\n"); dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info, 0, num_reserved_conf_bits - 1, VERILOG_PORT_INPUT); } /* Normal sram ports */ if (0 < num_conf_bits) { fprintf(fp, ",\n"); dump_verilog_sram_ports(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1, VERILOG_PORT_INPUT); } /* Dump ports only visible during formal verification*/ if (0 < num_conf_bits) { fprintf(fp, "\n"); fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag); fprintf(fp, ",\n"); dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_conf_bits - 1, VERILOG_PORT_INPUT); fprintf(fp, "\n"); fprintf(fp, "`endif\n"); } /* Local vdd and gnd*/ fprintf(fp, ");\n"); if (0 < num_sram_port) { dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1); } if (0 < num_sram_port) { switch (cur_sram_orgz_info->type) { case SPICE_SRAM_MEMORY_BANK: /* Local wires */ /* Find the number of BLs/WLs of each SRAM */ /* Detect the SRAM SPICE model linked to this SRAM port */ assert(NULL != sram_ports[0]->spice_model); assert(SPICE_MODEL_SRAM == sram_ports[0]->spice_model->type); find_bl_wl_ports_spice_model(sram_ports[0]->spice_model, &num_bl_ports, &bl_port, &num_wl_ports, &wl_port); assert(1 == num_bl_ports); assert(1 == num_wl_ports); break; case SPICE_SRAM_STANDALONE: case SPICE_SRAM_SCAN_CHAIN: break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n", __FILE__, __LINE__); exit(1); } } /* Definition ends*/ /* Dump the configuration port bus */ if ((0 < num_reserved_conf_bits) || (0 < num_conf_bits)) { dump_verilog_mem_config_bus(fp, mem_model, cur_sram_orgz_info, cur_num_sram, num_reserved_conf_bits, num_conf_bits); /* Dump ports only visible during formal verification*/ fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag); dump_verilog_formal_verification_sram_ports_wiring(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_conf_bits - 1); fprintf(fp, "`endif\n"); } /* Call the subckt*/ fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt); fprintf(fp, "\n"); /* Only dump the global ports belonging to a spice_model * Disable recursive here ! */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE, TRUE)) { fprintf(fp, ",\n"); } /* assert */ num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1); /* print ports --> input ports */ dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, FALSE, FALSE, TRUE); /* IOPADs requires a specical port to output */ if (SPICE_MODEL_IOPAD == verilog_model->type) { fprintf(fp, ",\n"); assert(1 == num_pad_port); assert(NULL != pad_ports[0]); /* Add explicit port mapping if required */ if (TRUE == verilog_model->dump_explicit_port_map) { fprintf(fp, ".%s(", pad_ports[0]->lib_name); } /* Print inout port */ fprintf(fp, "%s%s[%d]", gio_inout_prefix, verilog_model->prefix, verilog_model->cnt); if (TRUE == verilog_model->dump_explicit_port_map) { fprintf(fp, ")"); } fprintf(fp, ", "); } /* Print SRAM ports */ /* Connect srams: TODO: to find the SRAM model used by this Verilog model */ if (0 < num_sram) { switch (cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: break; case SPICE_SRAM_SCAN_CHAIN: /* Add explicit port mapping if required */ if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { assert( 1 == num_sram_port); assert( NULL != sram_ports[0]); fprintf(fp, ".%s(", sram_ports[0]->lib_name); } dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1, 0, VERILOG_PORT_CONKT); if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { fprintf(fp, ")"); } /* Check if we have an inverterd prefix */ if (NULL == sram_ports[0]->inv_prefix) { break; } fprintf(fp, ", "); /* Add explicit port mapping if required */ if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { assert( 1 == num_sram_port); assert( NULL != sram_ports[0]); fprintf(fp, ".%s(", sram_ports[0]->inv_prefix); } dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1, 1, VERILOG_PORT_CONKT); if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { fprintf(fp, ")"); } break; case SPICE_SRAM_MEMORY_BANK: /* Add explicit port mapping if required */ if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { assert( 1 == num_sram_port); assert( NULL != sram_ports[0]); fprintf(fp, ".%s(", sram_ports[0]->lib_name); } dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1, 0, VERILOG_PORT_CONKT); if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { fprintf(fp, ")"); } /* Check if we have an inverterd prefix */ if (NULL == sram_ports[0]->inv_prefix) { break; } fprintf(fp, ", "); /* Add explicit port mapping if required */ if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { assert( 1 == num_sram_port); assert( NULL != sram_ports[0]); fprintf(fp, ".%s(", sram_ports[0]->inv_prefix); } dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1, 1, VERILOG_PORT_CONKT); if ( (0 < num_sram) && (TRUE == verilog_model->dump_explicit_port_map)) { fprintf(fp, ")"); } break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n", __FILE__, __LINE__); exit(1); } } /* Local vdd and gnd, verilog_model name, * TODO: Global vdd for i/o pad to split? */ fprintf(fp, ");\n"); /* Call SRAM subckt */ /* what is the SRAM bit of a mode? */ /* If logical block is not NULL, we need to decode the sram bit */ /* SRAM bits are decoded in bitstream generator! NOT here if (NULL != mapped_logical_block) { assert(NULL != mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits); sram_bits = decode_mode_bits(mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits, &expected_num_sram); assert(expected_num_sram == num_sram); } else { sram_bits = (int*)my_calloc(num_sram, sizeof(int)); for (i = 0; i < num_sram; i++) { sram_bits[i] = sram_ports[0]->default_val; } } */ /* Call the memory module defined for this SRAM-based MUX! */ if (0 < num_sram_port) { mem_subckt_name = generate_verilog_mem_subckt_name(verilog_model, mem_model, verilog_mem_posfix); fprintf(fp, "%s %s_%d_ ( ", mem_subckt_name, mem_subckt_name, verilog_model->cnt); dump_verilog_mem_sram_submodule(fp, cur_sram_orgz_info, verilog_model, -1, mem_model, cur_num_sram, cur_num_sram + num_sram - 1); fprintf(fp, ");\n"); /* update the number of memory bits */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + num_sram); } /* End */ fprintf(fp, "endmodule\n"); /* Comment lines */ fprintf(fp, "//----- END %s Verilog module: %s%s -----\n\n", generate_string_spice_model_type(verilog_model->type), formatted_subckt_prefix, port_prefix); /* Update the verilog_model counter */ verilog_model->cnt++; /*Free*/ free(formatted_subckt_prefix); free(port_prefix); my_free(input_ports); my_free(output_ports); my_free(pad_ports); my_free(clock_ports); my_free(sram_ports); /* my_free(sram_bits); */ return; } void dump_verilog_pb_primitive_lut(t_sram_orgz_info* cur_sram_orgz_info, FILE* fp, char* subckt_prefix, t_pb_graph_node* prim_pb_graph_node, int index, t_spice_model* verilog_model) { int i, ipin; int lut_size = 0; int num_input_port = 0; t_spice_model_port** input_ports = NULL; int num_output_port = 0; t_spice_model_port** output_ports = NULL; int num_sram_port = 0; t_spice_model_port** sram_ports = NULL; int num_lut_sram = 0; int num_mode_sram = 0; t_spice_model_port* lut_sram_port = NULL; int num_pb_type_input_port = 0; t_port** pb_type_input_ports = NULL; int num_pb_type_output_port = 0; t_port** pb_type_output_ports = NULL; char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/ t_pb_type* cur_pb_type = NULL; char* port_prefix = NULL; int cur_num_sram = 0; int num_sram = 0; /* For each SRAM, we could have multiple BLs/WLs */ int num_bl_ports = 0; t_spice_model_port** bl_port = NULL; int num_wl_ports = 0; t_spice_model_port** wl_port = NULL; int num_bl_per_sram = 0; int num_wl_per_sram = 0; int num_conf_bits = 0; int num_reserved_conf_bits = 0; int cur_bl, cur_wl; t_spice_model* mem_model = NULL; char* mem_subckt_name = NULL; /* Ensure a valid file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n", __FILE__, __LINE__); exit(1); } /* Ensure a valid pb_graph_node */ if (NULL == prim_pb_graph_node) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n", __FILE__, __LINE__); exit(1); } /* Asserts */ assert(SPICE_MODEL_LUT == verilog_model->type); /* 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); assert(1 == num_input_port); lut_size = input_ports[0]->size; /* Find SRAM ports for truth tables and mode bits */ sram_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE); assert((1 == num_sram_port) || (2 == num_sram_port)); for (i = 0; i < num_sram_port; i++) { if (FALSE == sram_ports[i]->mode_select) { lut_sram_port = sram_ports[i]; num_lut_sram = sram_ports[i]->size; assert (num_lut_sram == (int)pow(2.,(double)(lut_size))); } else { assert (TRUE == sram_ports[i]->mode_select); num_mode_sram = sram_ports[i]->size; } } /* Must have a lut_sram_port, while mode_bit_port is optional */ assert (NULL != lut_sram_port); /* Count the number of configuration bits */ num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1); /* Get memory model */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); /* Find the number of BLs/WLs of each SRAM */ switch (cur_sram_orgz_info->type) { case SPICE_SRAM_MEMORY_BANK: /* Detect the SRAM SPICE model linked to this SRAM port */ assert(NULL != sram_ports[0]->spice_model); assert(SPICE_MODEL_SRAM == sram_ports[0]->spice_model->type); find_bl_wl_ports_spice_model(sram_ports[0]->spice_model, &num_bl_ports, &bl_port, &num_wl_ports, &wl_port); assert(1 == num_bl_ports); assert(1 == num_wl_ports); num_bl_per_sram = bl_port[0]->size; num_wl_per_sram = wl_port[0]->size; /* Asserts */ assert(num_bl_per_sram == num_wl_per_sram); break; case SPICE_SRAM_STANDALONE: case SPICE_SRAM_SCAN_CHAIN: break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n", __FILE__, __LINE__); exit(1); } /* Disable Generate sram bits*/ /* SRAM bits are decoded in bitstream generator! NOT here sram_bits = generate_lut_sram_bits(truth_table_length, truth_table, lut_size, sram_ports[0]->default_val); */ /* Print the subckts*/ cur_pb_type = prim_pb_graph_node->pb_type; /* Comment lines */ fprintf(fp, "//----- LUT Verilog module: %s%s_%d_ -----\n", formatted_subckt_prefix, cur_pb_type->name, index); /* Simplify the prefix, make the SPICE netlist readable*/ port_prefix = (char*)my_malloc(sizeof(char)* (strlen(cur_pb_type->name) + 1)); sprintf(port_prefix, "%s", cur_pb_type->name); /* Subckt definition*/ fprintf(fp, "module %s%s (", formatted_subckt_prefix, cur_pb_type->name); fprintf(fp, "\n"); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE, FALSE)) { fprintf(fp, ",\n"); } /* Print inputs, outputs, inouts, clocks, NO SRAMs*/ dump_verilog_pb_type_ports(fp, port_prefix, 0, cur_pb_type, TRUE, TRUE, FALSE); /* Print SRAM ports */ cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &cur_bl, &cur_wl); /* connect to reserved BL/WLs ? */ num_reserved_conf_bits = count_num_reserved_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0); /* Get the number of configuration bits required by this MUX */ num_conf_bits = count_num_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0); /* Reserved sram ports */ if ( 0 < num_reserved_conf_bits) { dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info, 0, num_reserved_conf_bits - 1, VERILOG_PORT_INPUT); fprintf(fp, ",\n"); } /* Normal sram ports */ if (0 < num_conf_bits) { dump_verilog_sram_ports(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_conf_bits - 1, VERILOG_PORT_INPUT); } /* Dump ports only visible during formal verification*/ if (0 < num_conf_bits) { fprintf(fp, "\n"); fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag); fprintf(fp, ",\n"); dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_conf_bits - 1, VERILOG_PORT_INPUT); fprintf(fp, "\n"); fprintf(fp, "`endif\n"); } /* Local Vdd and gnd*/ fprintf(fp, ");\n"); /* Definition ends*/ /* Specify inputs are wires */ pb_type_input_ports = find_pb_type_ports_match_spice_model_port_type(cur_pb_type, SPICE_MODEL_PORT_INPUT, &num_pb_type_input_port); assert(1 == num_pb_type_input_port); fprintf(fp, "wire [0:%d] %s__%s;\n", input_ports[0]->size - 1, port_prefix, pb_type_input_ports[0]->name); for (i = 0; i < input_ports[0]->size; i++) { fprintf(fp, "assign %s__%s[%d] = %s__%s_%d_;\n", port_prefix, pb_type_input_ports[0]->name, i, port_prefix, pb_type_input_ports[0]->name, i); } /* Specify outputs are wires */ pb_type_output_ports = find_pb_type_ports_match_spice_model_port_type(cur_pb_type, SPICE_MODEL_PORT_OUTPUT, &num_pb_type_output_port); for (i = 0; i < num_pb_type_output_port; i++) { fprintf(fp, "wire [0:%d] %s__%s;\n", output_ports[i]->size - 1, port_prefix, pb_type_output_ports[i]->name); } /* Make sure we have the same number outputs */ assert (num_pb_type_output_port == num_output_port); for (i = 0; i < num_output_port; i++) { for (ipin = 0; ipin < output_ports[i]->size; ipin++) { fprintf(fp, "assign %s__%s_%d_ = %s__%s[%d];\n", port_prefix, pb_type_output_ports[i]->name, ipin, port_prefix, pb_type_output_ports[i]->name, ipin); } } /* Specify SRAM output are wires */ cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1); /* Dump ports only visible during formal verification*/ if ((0 < num_reserved_conf_bits) || (0 < num_conf_bits)) { dump_verilog_mem_config_bus(fp, mem_model, cur_sram_orgz_info, cur_num_sram, num_reserved_conf_bits, num_conf_bits); fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag); dump_verilog_formal_verification_sram_ports_wiring(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1); fprintf(fp, "`endif\n"); } /* fprintf(fp, "wire [%d:%d] %s_out;\n", cur_num_sram, cur_num_sram + num_sram - 1, mem_model->prefix); fprintf(fp, "wire [%d:%d] %s_outb;\n", cur_num_sram, cur_num_sram + num_sram - 1, mem_model->prefix); */ num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1); cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); /* Call LUT subckt*/ fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt); fprintf(fp, "\n"); /* if we have to add global ports when dumping submodules of LUTs * otherwise, the port map here does not match that of submodules * Only dump the global ports belonging to a spice_model * DISABLE recursive here ! */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE, FALSE)) { fprintf(fp, ",\n"); } /* Connect inputs*/ /* Connect outputs*/ fprintf(fp, "//----- Input and output ports -----\n"); dump_verilog_pb_type_bus_ports(fp, port_prefix, 0, cur_pb_type, FALSE, TRUE); fprintf(fp, "\n//----- SRAM ports -----\n"); /* check */ assert (num_sram == num_lut_sram + num_mode_sram); /* Connect srams: TODO: to find the SRAM model used by this Verilog model */ cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); /* TODO: switch depending on the type of configuration circuit */ switch (cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: break; case SPICE_SRAM_SCAN_CHAIN: dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_lut_sram - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ", "); dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_lut_sram - 1, 1, VERILOG_PORT_CONKT); if (0 < num_mode_sram) { fprintf(fp, ", "); dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ", "); dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1, 1, VERILOG_PORT_CONKT); } break; case SPICE_SRAM_MEMORY_BANK: dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_lut_sram - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ", "); dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_lut_sram - 1, 1, VERILOG_PORT_CONKT); if (0 < num_mode_sram) { fprintf(fp, ", "); dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ", "); dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1, 1, VERILOG_PORT_CONKT); } break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n", __FILE__, __LINE__); exit(1); } /* vdd should be connected to special global wire gvdd_lut and gnd, * Every LUT has a special VDD for statistics */ fprintf(fp, ");\n"); /* Call SRAM subckts only * when Configuration organization style is memory bank */ /* No. of SRAMs is different from the number of configuration lines. * Especially when SRAMs/RRAMs are configured with BL/WLs */ num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1); cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); /* Call the memory module defined for this SRAM-based MUX! */ mem_subckt_name = generate_verilog_mem_subckt_name(verilog_model, mem_model, verilog_mem_posfix); fprintf(fp, "%s %s_%d_ ( ", mem_subckt_name, mem_subckt_name, verilog_model->cnt); dump_verilog_mem_sram_submodule(fp, cur_sram_orgz_info, verilog_model, -1, mem_model, cur_num_sram, cur_num_sram + num_sram - 1); fprintf(fp, ");\n"); /* update the number of memory bits */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + num_sram); /* End of subckt*/ fprintf(fp, "endmodule\n"); /* Comment lines */ fprintf(fp, "//----- END LUT Verilog module: %s%s_%d_ -----\n\n", formatted_subckt_prefix, cur_pb_type->name, index); /* Update counter */ verilog_model->cnt++; /*Free*/ my_free(formatted_subckt_prefix); my_free(input_ports); my_free(output_ports); my_free(sram_ports); my_free(mem_subckt_name); /* my_free(sram_bits); */ my_free(port_prefix); return; }