/***********************************/ /* Synthesizable Verilog Dumping */ /* Xifan TANG, EPFL/LSI */ /***********************************/ #include #include #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_util.h" #include "rr_graph.h" #include "rr_graph2.h" #include "vpr_utils.h" /* FPGA-SPICE utils */ #include "read_xml_spice_util.h" #include "linkedlist.h" #include "fpga_spice_utils.h" #include "fpga_spice_globals.h" /* syn_verilog globals */ #include "verilog_global.h" #include "verilog_utils.h" /****** Subroutines *******/ void init_list_include_verilog_netlists(t_spice* spice) { int i, j, cur; int to_include = 0; int num_to_include = 0; /* Initialize */ for (i = 0; i < spice->num_include_netlist; i++) { FreeSpiceModelNetlist(&(spice->include_netlists[i])); } my_free(spice->include_netlists); spice->include_netlists = NULL; spice->num_include_netlist = 0; /* Generate include netlist list */ vpr_printf(TIO_MESSAGE_INFO, "Listing Verilog Netlist Names to be included...\n"); for (i = 0; i < spice->num_spice_model; i++) { if (NULL != spice->spice_models[i].verilog_netlist) { /* Check if this netlist name has already existed in the list */ to_include = 1; for (j = 0; j < i; j++) { if (NULL == spice->spice_models[j].verilog_netlist) { continue; } if (0 == strcmp(spice->spice_models[j].verilog_netlist, spice->spice_models[i].verilog_netlist)) { to_include = 0; break; } } /* Increamental */ if (1 == to_include) { num_to_include++; } } } /* realloc */ spice->include_netlists = (t_spice_model_netlist*)my_realloc(spice->include_netlists, sizeof(t_spice_model_netlist)*(num_to_include + spice->num_include_netlist)); /* Fill the new included netlists */ cur = spice->num_include_netlist; for (i = 0; i < spice->num_spice_model; i++) { if (NULL != spice->spice_models[i].verilog_netlist) { /* Check if this netlist name has already existed in the list */ to_include = 1; for (j = 0; j < i; j++) { if (NULL == spice->spice_models[j].verilog_netlist) { continue; } if (0 == strcmp(spice->spice_models[j].verilog_netlist, spice->spice_models[i].verilog_netlist)) { to_include = 0; break; } } /* Increamental */ if (1 == to_include) { spice->include_netlists[cur].path = my_strdup(spice->spice_models[i].verilog_netlist); spice->include_netlists[cur].included = 0; vpr_printf(TIO_MESSAGE_INFO, "[%d] %s\n", cur+1, spice->include_netlists[cur].path); cur++; } } } /* Check */ assert(cur == (num_to_include + spice->num_include_netlist)); /* Update */ spice->num_include_netlist += num_to_include; return; } void init_include_user_defined_verilog_netlists(t_spice spice) { int i; /* Include user-defined sub-circuit netlist */ for (i = 0; i < spice.num_include_netlist; i++) { spice.include_netlists[i].included = 0; } return; } void dump_include_user_defined_verilog_netlists(FILE* fp, t_spice spice) { int i; /* A valid file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__); exit(1); } /* Include user-defined sub-circuit netlist */ for (i = 0; i < spice.num_include_netlist; i++) { if (0 == spice.include_netlists[i].included) { assert(NULL != spice.include_netlists[i].path); fprintf(fp, "// `include \"%s\"\n", spice.include_netlists[i].path); spice.include_netlists[i].included = 1; } else { assert(1 == spice.include_netlists[i].included); } } return; } /* Dump preproc */ void dump_verilog_preproc(FILE* fp, boolean include_timing) { if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s, LINE[%d]) FileHandle is NULL!\n",__FILE__,__LINE__); exit(1); } /* To enable timing */ if (TRUE == include_timing) { fprintf(fp, "`define %s 1\n", verilog_timing_preproc_flag); fprintf(fp, "\n"); } return; } void dump_verilog_file_header(FILE* fp, char* usage) { if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s, LINE[%d]) FileHandle is NULL!\n",__FILE__,__LINE__); exit(1); } fprintf(fp,"//-------------------------------------------\n"); fprintf(fp,"// FPGA Synthesizable Verilog Netlist \n"); fprintf(fp,"// Description: %s \n",usage); fprintf(fp,"// Author: Xifan TANG \n"); fprintf(fp,"// Organization: EPFL/IC/LSI \n"); fprintf(fp,"// Date: %s \n",my_gettime()); fprintf(fp,"//-------------------------------------------\n"); fprintf(fp,"//----- Time scale -----\n"); fprintf(fp,"`timescale 1ns / 1ps\n"); fprintf(fp,"\n"); return; } /* Create a file handler for a subckt Verilog netlist */ FILE* verilog_create_one_subckt_file(char* subckt_dir, char* subckt_name_prefix, char* verilog_subckt_file_name_prefix, int grid_x, int grid_y, char** verilog_fname) { FILE* fp = NULL; char* file_description = NULL; (*verilog_fname) = my_strcat(subckt_dir, fpga_spice_create_one_subckt_filename(verilog_subckt_file_name_prefix, grid_x, grid_y, verilog_netlist_file_postfix)); /* Create a file*/ fp = fopen((*verilog_fname), "w"); if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR, "(FILE:%s,LINE[%d])Failure in create Verilog netlist %s", __FILE__, __LINE__, (*verilog_fname)); exit(1); } /* Generate the descriptions*/ file_description = (char*) my_malloc(sizeof(char) * (strlen(subckt_name_prefix) + 2 + strlen(my_itoa(grid_x)) + 2 + strlen(my_itoa(grid_y)) + 9)); sprintf(file_description, "%s [%d][%d] in FPGA", subckt_name_prefix, grid_x, grid_y); dump_verilog_file_header(fp, file_description); /* Free */ my_free(file_description); return fp; } /* Output all the created subckt file names in a header file, * that can be easily imported in a top-level netlist */ void dump_verilog_subckt_header_file(t_llist* subckt_llist_head, char* subckt_dir, char* header_file_name) { FILE* fp = NULL; char* verilog_fname = NULL; t_llist* temp = NULL; verilog_fname = my_strcat(subckt_dir, header_file_name); /* Create a file*/ fp = fopen(verilog_fname, "w"); if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR, "(FILE:%s,LINE[%d])Failure in create Verilog netlist %s", __FILE__, __LINE__, verilog_fname); exit(1); } /* Generate the descriptions*/ dump_verilog_file_header(fp, "Header file"); /* Output file names */ temp = subckt_llist_head; while (temp) { fprintf(fp, "`include \"%s\"\n", (char*)(temp->dptr)); temp = temp->next; } /* Close fp */ fclose(fp); /* Free */ my_free(verilog_fname); return; } /* Determine the split sign for generic port */ char determine_verilog_generic_port_split_sign(enum e_dump_verilog_port_type dump_port_type) { char ret; switch (dump_port_type) { case VERILOG_PORT_INPUT: case VERILOG_PORT_OUTPUT: case VERILOG_PORT_INOUT: case VERILOG_PORT_CONKT: ret = ','; break; case VERILOG_PORT_WIRE: case VERILOG_PORT_REG: ret = ';'; break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of Verilog port to be dumped !\n", __FILE__, __LINE__); exit(1); } return ret; } /* Dump a generic Verilog port */ void dump_verilog_generic_port(FILE* fp, enum e_dump_verilog_port_type dump_port_type, char* port_name, int port_lsb, int port_msb) { boolean dump_single_port = FALSE; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Check */ assert((!(port_lsb < 0))&&(!(port_msb < 0))); if (port_lsb == port_msb) { dump_single_port = TRUE; } dump_single_port = FALSE; /* Disable it for a clear synthesis */ switch (dump_port_type) { case VERILOG_PORT_INPUT: if (TRUE == dump_single_port) { fprintf(fp,"input %s ", port_name); } else { assert(FALSE == dump_single_port); fprintf(fp,"input [%d:%d] %s ", port_lsb, port_msb, port_name); } break; case VERILOG_PORT_OUTPUT: if (TRUE == dump_single_port) { fprintf(fp,"output %s ", port_name); } else { assert(FALSE == dump_single_port); fprintf(fp,"output [%d:%d] %s ", port_lsb, port_msb, port_name); } break; case VERILOG_PORT_INOUT: if (TRUE == dump_single_port) { fprintf(fp,"inout %s ", port_name); } else { assert(FALSE == dump_single_port); fprintf(fp,"inout [%d:%d] %s ", port_lsb, port_msb, port_name); } break; case VERILOG_PORT_WIRE: if (TRUE == dump_single_port) { fprintf(fp,"wire %s ", port_name); } else { assert(FALSE == dump_single_port); fprintf(fp,"wire [%d:%d] %s ", port_lsb, port_msb, port_name); } break; case VERILOG_PORT_REG: if (TRUE == dump_single_port) { fprintf(fp,"reg %s ", port_name); } else { assert(FALSE == dump_single_port); fprintf(fp,"reg [%d:%d] %s ", port_lsb, port_msb, port_name); } break; case VERILOG_PORT_CONKT: if (TRUE == dump_single_port) { fprintf(fp,"%s ", port_name); } else { assert(FALSE == dump_single_port); fprintf(fp,"%s[%d:%d] ", port_name, port_lsb, port_msb); } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of Verilog port to be dumped !\n", __FILE__, __LINE__); exit(1); } return; } /* Decode BL and WL bits for a SRAM * SRAM could be * 1. NV SRAM * or * 2. SRAM */ void decode_verilog_memory_bank_sram(t_spice_model* cur_sram_spice_model, int sram_bit, int bl_len, int wl_len, int bl_offset, int wl_offset, int* bl_conf_bits, int* wl_conf_bits) { int i; /* Check */ assert(NULL != cur_sram_spice_model); assert(NULL != bl_conf_bits); assert(NULL != wl_conf_bits); assert((1 == sram_bit)||(0 == sram_bit)); /* All the others should be zero */ for (i = 0; i < bl_len; i++) { bl_conf_bits[i] = 0; } for (i = 0; i < wl_len; i++) { wl_conf_bits[i] = 0; } /* Depending on the design technology of SRAM */ switch (cur_sram_spice_model->design_tech) { case SPICE_MODEL_DESIGN_CMOS: /* CMOS SRAM */ /* Make sure there is only 1 BL and 1 WL */ assert((1 == bl_len)&&(1 == wl_len)); /* We always assume that WL is a write-enable signal * While BL contains what data will be written into SRAM */ bl_conf_bits[0] = sram_bit; wl_conf_bits[0] = 1; break; case SPICE_MODEL_DESIGN_RRAM: /* NV SRAM (RRAM-based) */ /* We need at least 2 BLs and 2 WLs but no more than 3, See schematic in manual */ /* Whatever the number of BLs and WLs, (RRAM0) * when sram bit is 1, last bit of BL should be enabled * while first bit of WL should be enabled at the same time * when sram bit is 0, last bit of WL should be enabled * while first bit of BL should be enabled at the same time */ assert((1 < bl_len)&&(bl_len < 4)); assert((1 < wl_len)&&(wl_len < 4)); assert((-1 < bl_offset)&&(bl_offset < bl_len)); assert((-1 < wl_offset)&&(wl_offset < wl_len)); /* In addition, we will may need two programing cycles. * The first cycle is dedicated to programming RRAM0 * The second cycle is dedicated to programming RRAM1 */ if (1 == sram_bit) { bl_conf_bits[bl_len-1] = 1; wl_conf_bits[0 + wl_offset] = 1; } else { assert(0 == sram_bit); bl_conf_bits[0 + bl_offset] = 1; wl_conf_bits[wl_len-1] = 1; } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology for SRAM!\n", __FILE__, __LINE__); exit(1); } return; } /* Decode one SRAM bit for memory-bank-style configuration circuit, and add it to linked list */ void decode_and_add_verilog_sram_membank_conf_bit_to_llist(t_sram_orgz_info* cur_sram_orgz_info, int mem_index, int num_bl_per_sram, int num_wl_per_sram, int cur_sram_bit) { int j; int* conf_bits_per_sram = NULL; t_spice_model* mem_model = NULL; /* Check */ assert( SPICE_SRAM_MEMORY_BANK == cur_sram_orgz_info->type ); /* Get memory model */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); assert(NULL != mem_model); /* Malloc/Calloc */ conf_bits_per_sram = (int*)my_calloc(num_bl_per_sram + num_wl_per_sram, sizeof(int)); /* Depend on the memory technology, we have different configuration bits */ switch (mem_model->design_tech) { case SPICE_MODEL_DESIGN_CMOS: /* Check */ assert((1 == num_bl_per_sram) && (1 == num_wl_per_sram)); /* For CMOS SRAM */ decode_verilog_memory_bank_sram(mem_model, cur_sram_bit, num_bl_per_sram, num_wl_per_sram, 0, 0, conf_bits_per_sram, conf_bits_per_sram + num_bl_per_sram); /* Use memory model here! Design technology of memory model determines the decoding strategy, instead of LUT model*/ add_sram_conf_bits_to_llist(cur_sram_orgz_info, mem_index, num_bl_per_sram + num_wl_per_sram, conf_bits_per_sram); break; case SPICE_MODEL_DESIGN_RRAM: /* Decode the SRAM bits to BL/WL bits. * first half part is BL, the other half part is WL */ /* Store the configuraion bit to linked-list */ assert(num_bl_per_sram == num_wl_per_sram); /* When the number of BL/WL is more than 1, we need multiple programming cycles to configure a SRAM */ /* ONLY valid for NV SRAM !!!*/ for (j = 0; j < num_bl_per_sram - 1; j++) { if (0 == j) { /* Store the configuraion bit to linked-list */ decode_verilog_memory_bank_sram(mem_model, cur_sram_bit, num_bl_per_sram, num_wl_per_sram, j, j, conf_bits_per_sram, conf_bits_per_sram + num_bl_per_sram); } else { /* Store the configuraion bit to linked-list */ decode_verilog_memory_bank_sram(mem_model, 1 - cur_sram_bit, num_bl_per_sram, num_wl_per_sram, j, j, conf_bits_per_sram, conf_bits_per_sram + num_bl_per_sram); } /* Use memory model here! Design technology of memory model determines the decoding strategy, instead of LUT model*/ add_sram_conf_bits_to_llist(cur_sram_orgz_info, mem_index, num_bl_per_sram + num_wl_per_sram, conf_bits_per_sram); } break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid design technology!", __FILE__, __LINE__); exit(1); } /* Free */ my_free(conf_bits_per_sram); return; } /** Decode 1-level 4T1R MUX */ void decode_verilog_one_level_4t1r_mux(int path_id, int bit_len, int* conf_bits) { int i; /* Check */ assert(0 < bit_len); assert(NULL != conf_bits); assert((-1 < path_id)&&((path_id < bit_len/2 - 1)||(path_id == bit_len/2 - 1))); /* All the others should be zero */ for (i = 0; i < bit_len; i++) { conf_bits[i] = 0; } /* Last bit of WL should be 1 */ conf_bits[bit_len-1] = 1; /* determine which BL should be 1*/ conf_bits[path_id] = 1; return; } /** Decode multi-level 4T1R MUX */ void decode_verilog_multilevel_4t1r_mux(int num_level, int num_input_basis, int mux_size, int path_id, int bit_len, int* conf_bits) { int i, active_basis_path_id; /* Check */ assert(0 < bit_len); assert(NULL != conf_bits); /* assert((-1 < path_id)&&(path_id < bit_len/2 - 1)); */ /* Start from first level to the last level */ active_basis_path_id = path_id; for (i = 0; i < num_level; i++) { /* Treat each basis as a 1-level 4T1R MUX */ active_basis_path_id = active_basis_path_id % num_input_basis; /* Last bit of WL should be 1 */ conf_bits[bit_len/2 + (num_input_basis+1)*(i+1) - 1] = 1; /* determine which BL should be 1*/ conf_bits[(num_input_basis+1)*i + active_basis_path_id] = 1; } return; } /** Decode the configuration bits for a 4T1R-based MUX * Determine the number of configuration bits * Configuration bits are decoded depending on the MUX structure: * 1. 1-level; 2. multi-level (tree-like); */ void decode_verilog_rram_mux(t_spice_model* mux_spice_model, int mux_size, int path_id, int* bit_len, int** conf_bits, int* mux_level) { int num_level, num_input_basis; /* Check */ assert(NULL != mux_level); assert(NULL != bit_len); assert(NULL != conf_bits); assert((-1 < path_id)&&(path_id < mux_size)); assert(SPICE_MODEL_MUX == mux_spice_model->type); assert(SPICE_MODEL_DESIGN_RRAM == mux_spice_model->design_tech); /* Initialization */ (*mux_level) = 0; (*bit_len) = 0; (*conf_bits) = NULL; (*bit_len) = 2 * count_num_sram_bits_one_spice_model(mux_spice_model, mux_size); /* Switch cases: MUX structure */ switch (mux_spice_model->design_tech_info.structure) { case SPICE_MODEL_STRUCTURE_ONELEVEL: /* Number of configuration bits is 2*(input_size+1) */ num_level = 1; break; case SPICE_MODEL_STRUCTURE_TREE: /* Number of configuration bits is num_level* 2*(basis+1) */ num_level = determine_tree_mux_level(mux_size); num_input_basis = 2; break; case SPICE_MODEL_STRUCTURE_MULTILEVEL: /* Number of configuration bits is num_level* 2*(basis+1) */ num_level = mux_spice_model->design_tech_info.mux_num_level; num_input_basis = determine_num_input_basis_multilevel_mux(mux_size, num_level); break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid MUX structure!\n", __FILE__, __LINE__); exit(1); } /* Malloc configuration bits */ (*conf_bits) = (int*)my_calloc((*bit_len), sizeof(int)); /* Decode configuration bits : BL & WL*/ /* Switch cases: MUX structure */ switch (mux_spice_model->design_tech_info.structure) { case SPICE_MODEL_STRUCTURE_ONELEVEL: decode_verilog_one_level_4t1r_mux(path_id, (*bit_len), (*conf_bits)); break; case SPICE_MODEL_STRUCTURE_TREE: case SPICE_MODEL_STRUCTURE_MULTILEVEL: decode_verilog_multilevel_4t1r_mux(num_level, num_input_basis, mux_size, path_id, (*bit_len), (*conf_bits)); break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid MUX structure!\n", __FILE__, __LINE__); exit(1); } (*mux_level) = num_level; return; } /* Determine the size of input address of a decoder */ int determine_decoder_size(int num_addr_out) { return ceil(log(num_addr_out)/log(2.)); } char* chomp_verilog_node_prefix(char* verilog_node_prefix) { int len = 0; char* ret = NULL; if (NULL == verilog_node_prefix) { return NULL; } len = strlen(verilog_node_prefix); /* String length without the last "\0"*/ ret = (char*)my_malloc(sizeof(char)*(len+1)); /* Don't do anything when input is NULL*/ if (NULL == verilog_node_prefix) { my_free(ret); return NULL; } strcpy(ret,verilog_node_prefix); /* If the path end up with "_" we should remove it*/ /* if ('_' == ret[len-1]) { ret[len-1] = ret[len]; } */ return ret; } char* format_verilog_node_prefix(char* verilog_node_prefix) { int len = strlen(verilog_node_prefix); /* String length without the last "\0"*/ char* ret = (char*)my_malloc(sizeof(char)*(len+1)); /* Don't do anything when input is NULL*/ if (NULL == verilog_node_prefix) { my_free(ret); return NULL; } strcpy(ret,verilog_node_prefix); /* If the path does not end up with "_" we should complete it*/ /* if (ret[len-1] != '_') { strcat(ret, "_"); } */ return ret; } /* Return the port_type in a verilog format */ char* verilog_convert_port_type_to_string(enum e_spice_model_port_type port_type) { switch (port_type) { case SPICE_MODEL_PORT_INPUT: case SPICE_MODEL_PORT_CLOCK: case SPICE_MODEL_PORT_SRAM: case SPICE_MODEL_PORT_BL: case SPICE_MODEL_PORT_WL: return "input"; case SPICE_MODEL_PORT_OUTPUT: return "output"; case SPICE_MODEL_PORT_INOUT: return "inout"; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s, [LINE%d])Invalid port type!\n", __FILE__, __LINE__); exit(1); } return NULL; } /* Dump all the global ports that are stored in the linked list * Return the number of ports that have been dumped */ int rec_dump_verilog_spice_model_global_ports(FILE* fp, t_spice_model* cur_spice_model, boolean dump_port_type, boolean recursive) { int iport, dumped_port_cnt, rec_dumped_port_cnt; boolean dump_comma = FALSE; dumped_port_cnt = 0; rec_dumped_port_cnt = 0; /* Check */ assert(NULL != cur_spice_model); if (0 < cur_spice_model->num_port) { assert(NULL != cur_spice_model->ports); } /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); } for (iport = 0; iport < cur_spice_model->num_port; iport++) { /* if this spice model requires customized netlist to be included, we do not go recursively */ if (TRUE == recursive) { /* GO recursively first, and meanwhile count the number of global ports */ /* For the port that requires another spice_model, i.e., SRAM * We need include any global port in that spice model */ if (NULL != cur_spice_model->ports[iport].spice_model) { /* Check if we need to dump a comma */ if (TRUE == dump_comma) { fprintf(fp, ",\n"); } rec_dumped_port_cnt += rec_dump_verilog_spice_model_global_ports(fp, cur_spice_model->ports[iport].spice_model, dump_port_type, recursive); /* Decide if we need a comma */ if (0 < rec_dumped_port_cnt) { dump_comma = TRUE; } /* Update counter */ dumped_port_cnt += rec_dumped_port_cnt; continue; } } /* By pass non-global ports*/ if (FALSE == cur_spice_model->ports[iport].is_global) { continue; } /* We have some port to dump ! * Print a comment line */ if (0 == dumped_port_cnt) { fprintf(fp, "//----- BEGIN Global ports of SPICE_MODEL(%s) -----\n", cur_spice_model->name); } /* Check if we need to dump a comma */ if (TRUE == dump_comma) { fprintf(fp, ",\n"); } if (TRUE == dump_port_type) { fprintf(fp, "%s [0:%d] %s", verilog_convert_port_type_to_string(cur_spice_model->ports[iport].type), cur_spice_model->ports[iport].size - 1, cur_spice_model->ports[iport].prefix); } else { fprintf(fp, "%s[0:%d]", cur_spice_model->ports[iport].prefix, cur_spice_model->ports[iport].size - 1); } /* Decide if we need a comma */ dump_comma = TRUE; /* Update counter */ dumped_port_cnt++; } /* We have dumped some port! * Print another comment line */ if (0 < dumped_port_cnt) { fprintf(fp, "\n"); fprintf(fp, "//----- END Global ports of SPICE_MODEL(%s)-----\n", cur_spice_model->name); } return dumped_port_cnt; } /* Dump all the global ports that are stored in the linked list */ int dump_verilog_global_ports(FILE* fp, t_llist* head, boolean dump_port_type) { t_llist* temp = head; t_spice_model_port* cur_global_port = NULL; int dumped_port_cnt = 0; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); } fprintf(fp, "//----- BEGIN Global ports -----\n"); while(NULL != temp) { cur_global_port = (t_spice_model_port*)(temp->dptr); if (TRUE == dump_port_type) { fprintf(fp, "%s [0:%d] %s", verilog_convert_port_type_to_string(cur_global_port->type), cur_global_port->size - 1, cur_global_port->prefix); } else { fprintf(fp, "%s[0:%d]", cur_global_port->prefix, cur_global_port->size - 1); } /* if this is the tail, we do not dump a comma */ if (NULL != temp->next) { fprintf(fp, ","); } fprintf(fp, "\n"); /* Update counter */ dumped_port_cnt++; /* Go to the next */ temp = temp->next; } fprintf(fp, "//----- END Global ports -----\n"); return dumped_port_cnt; } /* Always dump the output ports of a SRAM in MUX */ void dump_verilog_mux_sram_one_outport(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, t_spice_model* cur_mux_spice_model, int mux_size, int sram_lsb, int sram_msb, int port_type_index, enum e_dump_verilog_port_type dump_port_type) { t_spice_model* mem_model = NULL; char* port_name = NULL; char* port_full_name = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Get memory_model */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); /* Keep the branch as it is, in case thing may become more complicated*/ switch (cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: if (0 == port_type_index) { port_name = "out"; } else { assert(1 == port_type_index); port_name = "outb"; } break; case SPICE_SRAM_SCAN_CHAIN: if (0 == port_type_index) { port_name = "out"; } else { assert(1 == port_type_index); port_name = "outb"; } break; case SPICE_SRAM_MEMORY_BANK: if (0 == port_type_index) { port_name = "out"; } else { assert(1 == port_type_index); port_name = "outb"; } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization !\n", __FILE__, __LINE__); exit(1); } /*Malloc and generate the full name of port */ port_full_name = (char*)my_malloc(sizeof(char)* (strlen(cur_mux_spice_model->prefix) + 5 + strlen(my_itoa(mux_size)) + 1 + strlen(my_itoa(cur_mux_spice_model->cnt)) + 1 + strlen(mem_model->prefix) + 1 + strlen(port_name) + 1)); sprintf(port_full_name, "%s_size%d_%d_%s_%s", cur_mux_spice_model->prefix, mux_size, cur_mux_spice_model->cnt, mem_model->prefix, port_name); dump_verilog_generic_port(fp, dump_port_type, port_full_name, sram_lsb, sram_msb); /* Free */ /* Local variables such as port1_name and port2 name are automatically freed */ my_free(port_full_name); return; } /* Always dump the output ports of a SRAM */ void dump_verilog_sram_one_outport(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, int sram_lsb, int sram_msb, int port_type_index, enum e_dump_verilog_port_type dump_port_type) { t_spice_model* mem_model = NULL; char* port_name = NULL; char* port_full_name = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Get memory_model */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); /* Keep the branch as it is, in case thing may become more complicated*/ switch (cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: if (0 == port_type_index) { port_name = "out"; } else { assert(1 == port_type_index); port_name = "outb"; } break; case SPICE_SRAM_SCAN_CHAIN: if (0 == port_type_index) { port_name = "scff_out"; } else { assert(1 == port_type_index); port_name = "scff_outb"; } break; case SPICE_SRAM_MEMORY_BANK: if (0 == port_type_index) { port_name = "out"; } else { assert(1 == port_type_index); port_name = "outb"; } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization !\n", __FILE__, __LINE__); exit(1); } /*Malloc and generate the full name of port */ port_full_name = (char*)my_malloc(sizeof(char)*(strlen(mem_model->prefix) + strlen(port_name) + 1 + 1)); sprintf(port_full_name, "%s_%s", mem_model->prefix, port_name); dump_verilog_generic_port(fp, dump_port_type, port_full_name, sram_lsb, sram_msb); /* Free */ /* Local variables such as port1_name and port2 name are automatically freed */ my_free(port_full_name); return; } /* Dump SRAM output ports, including two ports, out and outb */ void dump_verilog_sram_outports(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, int sram_lsb, int sram_msb, enum e_dump_verilog_port_type dump_port_type) { /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } if (0 > (sram_msb - sram_lsb)) { return; } if ((sram_lsb < 0)||(sram_msb < 0)) { vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid sram_lsb(%d) and sram_msb(%d)!\n", __FILE__, __LINE__, sram_lsb, sram_msb); return; } /* Dump the first port: SRAM_out of CMOS MUX or BL of RRAM MUX */ dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 0, dump_port_type); fprintf(fp, ",\n"); /* Dump the first port: SRAM_outb of CMOS MUX or WL of RRAM MUX */ dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 1, dump_port_type); return; } void dump_verilog_sram_one_port(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, int sram_lsb, int sram_msb, int port_type_index, enum e_dump_verilog_port_type dump_port_type) { t_spice_model* mem_model = NULL; char* port_name = NULL; char* port_full_name = NULL; enum e_dump_verilog_port_type actual_dump_port_type = dump_port_type; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Get memory_model */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); switch (cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: mem_model = cur_sram_orgz_info->standalone_sram_info->mem_model; if (0 == port_type_index) { port_name = "out"; } else { assert(1 == port_type_index); port_name = "outb"; } break; case SPICE_SRAM_SCAN_CHAIN: mem_model = cur_sram_orgz_info->scff_info->mem_model; if (0 == port_type_index) { port_name = "scff_in"; } else { assert(1 == port_type_index); port_name = "scff_out"; /* Special case: scan-chain ff output should be an output always */ if (VERILOG_PORT_INPUT == dump_port_type) { actual_dump_port_type = VERILOG_PORT_OUTPUT; } } break; case SPICE_SRAM_MEMORY_BANK: mem_model = cur_sram_orgz_info->mem_bank_info->mem_model; if (0 == port_type_index) { port_name = "bl"; } else if (1 == port_type_index) { port_name = "wl"; /* Create inverted BL and WL signals */ } else if (2 == port_type_index) { port_name = "blb"; } else if (3 == port_type_index) { port_name = "wlb"; } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization !\n", __FILE__, __LINE__); exit(1); } /*Malloc and generate the full name of port */ port_full_name = (char*)my_malloc(sizeof(char)*(strlen(mem_model->prefix) + strlen(port_name) + 1 + 1)); sprintf(port_full_name, "%s_%s", mem_model->prefix, port_name); dump_verilog_generic_port(fp, actual_dump_port_type, port_full_name, sram_lsb, sram_msb); /* Free */ /* Local variables such as port1_name and port2 name are automatically freed */ my_free(port_full_name); return; } /* Dump SRAM ports, which is supposed to be the last port in the port list */ void dump_verilog_sram_ports(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, int sram_lsb, int sram_msb, enum e_dump_verilog_port_type dump_port_type) { /* Need to dump inverted BL/WL if needed */ int num_blb_ports, num_wlb_ports; t_spice_model_port** blb_port = NULL; t_spice_model_port** wlb_port = NULL; t_spice_model* cur_sram_verilog_model = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } if (0 > (sram_msb - sram_lsb)) { return; } if ((sram_lsb < 0)||(sram_msb < 0)) { vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid sram_lsb(%d) and sram_msb(%d)!\n", __FILE__, __LINE__, sram_lsb, sram_msb); return; } /* Dump the first port: SRAM_out of CMOS MUX or BL of RRAM MUX */ dump_verilog_sram_one_port(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 0, dump_port_type); fprintf(fp, ",\n"); /* Dump the first port: SRAM_outb of CMOS MUX or WL of RRAM MUX */ dump_verilog_sram_one_port(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 1, dump_port_type); /* Find the BLB and WLB port, if there is any */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &cur_sram_verilog_model); find_blb_wlb_ports_spice_model(cur_sram_verilog_model, &num_blb_ports, &blb_port, &num_wlb_ports, &wlb_port); /* BL inverted port */ if (1 == num_blb_ports) { fprintf(fp, ",\n"); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 2, dump_port_type); } /* WL inverted port */ if (1 == num_wlb_ports) { fprintf(fp, ",\n"); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 3, dump_port_type); } return; } void dump_verilog_reserved_sram_one_port(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, int sram_lsb, int sram_msb, int port_type_index, enum e_dump_verilog_port_type dump_port_type) { t_spice_model* mem_model = NULL; char* port_name = NULL; char* port_full_name = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } switch (cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: case SPICE_SRAM_SCAN_CHAIN: return; case SPICE_SRAM_MEMORY_BANK: get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); if (0 == port_type_index) { port_name = "reserved_bl"; } else { assert(1 == port_type_index); port_name = "reserved_wl"; } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization !\n", __FILE__, __LINE__); exit(1); } /*Malloc and generate the full name of port */ port_full_name = (char*)my_malloc(sizeof(char)*(strlen(mem_model->prefix) + strlen(port_name) + 1 + 1)); sprintf(port_full_name, "%s_%s", mem_model->prefix, port_name); dump_verilog_generic_port(fp, dump_port_type, port_full_name, sram_lsb, sram_msb); /* Free */ /* Local variables such as port1_name and port2 name are automatically freed */ my_free(port_full_name); return; } /* Dump SRAM ports, which is supposed to be the last port in the port list */ void dump_verilog_reserved_sram_ports(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, int sram_lsb, int sram_msb, enum e_dump_verilog_port_type dump_port_type) { /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } if (0 > (sram_msb - sram_lsb)) { return; } /* Dump the first port: SRAM_out of CMOS MUX or BL of RRAM MUX */ if ((sram_lsb < 0)||(sram_msb < 0)) { vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid sram_lsb(%d) and sram_msb(%d)!\n", __FILE__, __LINE__, sram_lsb, sram_msb); return; } dump_verilog_reserved_sram_one_port(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 0, dump_port_type); fprintf(fp, ",\n"); /* Dump the first port: SRAM_outb of CMOS MUX or WL of RRAM MUX */ dump_verilog_reserved_sram_one_port(fp, cur_sram_orgz_info, sram_lsb, sram_msb, 1, dump_port_type); return; } /* Dump a verilog submodule of SRAMs in MUX, according to SRAM organization type */ void dump_verilog_mux_sram_submodule(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, t_spice_model* cur_mux_verilog_model, int mux_size, t_spice_model* cur_sram_verilog_model) { int cur_bl, cur_wl, cur_num_sram; int num_bl_ports, num_wl_ports; t_spice_model_port** bl_port = NULL; t_spice_model_port** wl_port = NULL; int num_blb_ports, num_wlb_ports; t_spice_model_port** blb_port = NULL; t_spice_model_port** wlb_port = NULL; int num_bl_per_sram = 0; int num_wl_per_sram = 0; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } assert(NULL != cur_sram_orgz_info); assert(NULL != cur_sram_verilog_model); assert((SPICE_MODEL_SRAM == cur_sram_verilog_model->type) || (SPICE_MODEL_SCFF == cur_sram_verilog_model->type)); /* Get current index of SRAM module */ cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); switch (cur_sram_orgz_info->type) { case SPICE_SRAM_MEMORY_BANK: /* Detect the SRAM SPICE model linked to this SRAM port */ find_bl_wl_ports_spice_model(cur_sram_verilog_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; /* Find the BLB and WLB port, if there is any */ find_blb_wlb_ports_spice_model(cur_sram_verilog_model, &num_blb_ports, &blb_port, &num_wlb_ports, &wlb_port); if (1 == num_blb_ports) { assert(num_bl_per_sram == blb_port[0]->size); } else { assert(0 == num_blb_ports); } if (1 == num_wlb_ports) { assert(num_wl_per_sram == wlb_port[0]->size); } else { assert(0 == num_wlb_ports); } /* SRAM subckts*/ fprintf(fp, "%s %s_%d_ (", cur_sram_verilog_model->name, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, cur_sram_verilog_model, FALSE, TRUE)) { fprintf(fp, ",\n"); } dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, cur_mux_verilog_model, mux_size, cur_num_sram, cur_num_sram, 0, VERILOG_PORT_CONKT); fprintf(fp, ","); dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, cur_mux_verilog_model, mux_size, cur_num_sram, cur_num_sram, 0, VERILOG_PORT_CONKT); fprintf(fp, ","); dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, cur_mux_verilog_model, mux_size, cur_num_sram, cur_num_sram, 1, VERILOG_PORT_CONKT); fprintf(fp, ","); get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &cur_bl, &cur_wl); /* Connect to Bit lines and Word lines, consider each conf_bit */ fprintf(fp, "%s_size%d_%d_configbus0[%d:%d], ", cur_mux_verilog_model->prefix, mux_size, cur_mux_verilog_model->cnt, cur_num_sram, cur_num_sram + num_bl_per_sram - 1); fprintf(fp, "%s_size%d_%d_configbus1[%d:%d] ", cur_mux_verilog_model->prefix, mux_size, cur_mux_verilog_model->cnt, cur_num_sram, cur_num_sram + num_wl_per_sram - 1); /* Outputs */ /* If we have a BLB or WLB, we need to dump inverted config_bus */ if (1 == num_blb_ports) { fprintf(fp, ", "); fprintf(fp, "%s_size%d_%d_configbus0_b[%d:%d] ", cur_mux_verilog_model->prefix, mux_size, cur_mux_verilog_model->cnt, cur_num_sram, cur_num_sram + num_bl_per_sram - 1); } if (1 == num_wlb_ports) { fprintf(fp, ", "); fprintf(fp, "%s_size%d_%d_configbus1_b[%d:%d] ", cur_mux_verilog_model->prefix, mux_size, cur_mux_verilog_model->cnt, cur_num_sram, cur_num_sram + num_wl_per_sram - 1); } fprintf(fp, ");\n"); // /* Update the counter */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + 1); update_sram_orgz_info_num_blwl(cur_sram_orgz_info, cur_bl + 1, cur_wl + 1); break; case SPICE_SRAM_STANDALONE: /* SRAM subckts*/ fprintf(fp, "%s %s_%d_ (", cur_sram_verilog_model->name, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, cur_sram_verilog_model, FALSE, TRUE)) { fprintf(fp, ",\n"); } fprintf(fp, "%s_out[%d], ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Input*/ fprintf(fp, "%s_out[%d], %s_outb[%d] ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Outputs */ fprintf(fp, ");\n"); // /* Update the counter */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + 1); break; case SPICE_SRAM_SCAN_CHAIN: /* Add a scan-chain DFF module here ! */ fprintf(fp, "%s %s_%d_ (", cur_sram_verilog_model->name, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, cur_sram_verilog_model, FALSE, TRUE)) { fprintf(fp, ",\n"); } /* Input of Scan-chain DFF, should be connected to the output of its precedent */ dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram, 0, VERILOG_PORT_CONKT); fprintf(fp, ", \n"); // /* Output of Scan-chain DFF, should be connected to the output of its successor */ dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram, 1, VERILOG_PORT_CONKT); fprintf(fp, ", \n"); // /* Memory outputs of Scan-chain DFF, should be connected to the SRAM(memory port) of IOPAD, MUX and LUT */ dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, cur_mux_verilog_model, mux_size, cur_num_sram, cur_num_sram, 1, VERILOG_PORT_CONKT); fprintf(fp, ");\n"); // /* Update the counter */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + 1); break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n", __FILE__, __LINE__); exit(1); } /* Update the counter */ cur_sram_verilog_model->cnt++; return; } /* Dump a verilog submodule of SRAM, according to SRAM organization type */ void dump_verilog_sram_submodule(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, t_spice_model* cur_sram_verilog_model) { int cur_bl, cur_wl, cur_num_sram; int num_bl_ports, num_wl_ports; t_spice_model_port** bl_port = NULL; t_spice_model_port** wl_port = NULL; int num_blb_ports, num_wlb_ports; t_spice_model_port** blb_port = NULL; t_spice_model_port** wlb_port = NULL; int num_bl_per_sram = 0; int num_wl_per_sram = 0; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } assert(NULL != cur_sram_orgz_info); assert(NULL != cur_sram_verilog_model); assert((SPICE_MODEL_SRAM == cur_sram_verilog_model->type) || (SPICE_MODEL_SCFF == cur_sram_verilog_model->type)); /* Get current index of SRAM module */ cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); switch (cur_sram_orgz_info->type) { case SPICE_SRAM_MEMORY_BANK: /* Detect the SRAM SPICE model linked to this SRAM port */ find_bl_wl_ports_spice_model(cur_sram_verilog_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; /* Find the BLB and WLB port, if there is any */ find_blb_wlb_ports_spice_model(cur_sram_verilog_model, &num_blb_ports, &blb_port, &num_wlb_ports, &wlb_port); if (1 == num_blb_ports) { assert(num_bl_per_sram == blb_port[0]->size); } else { assert(0 == num_blb_ports); } if (1 == num_wlb_ports) { assert(num_wl_per_sram == wlb_port[0]->size); } else { assert(0 == num_wlb_ports); } /* SRAM subckts*/ fprintf(fp, "%s %s_%d_ (", cur_sram_verilog_model->name, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, cur_sram_verilog_model, FALSE, TRUE)) { fprintf(fp, ",\n"); } fprintf(fp, "%s_out[%d], ", cur_sram_verilog_model->prefix, cur_num_sram); /* Input*/ fprintf(fp, "%s_out[%d], %s_outb[%d], ", cur_sram_verilog_model->prefix, cur_num_sram, cur_sram_verilog_model->prefix, cur_num_sram); /* Outputs */ get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &cur_bl, &cur_wl); /* Connect to Bit lines and Word lines, consider each conf_bit */ fprintf(fp, "%s_%d_configbus0[%d:%d], ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt, cur_bl, cur_bl + num_bl_per_sram - 1); fprintf(fp, "%s_%d_configbus1[%d:%d] ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt, cur_wl, cur_wl + num_wl_per_sram - 1); /* Outputs */ if (1 == num_blb_ports) { fprintf(fp, ", "); fprintf(fp, "%s_%d_configbus0_b[%d:%d] ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt, cur_bl, cur_bl + num_bl_per_sram - 1); } if (1 == num_wlb_ports) { fprintf(fp, ", "); fprintf(fp, "%s_%d_configbus1_b[%d:%d] ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt, cur_wl, cur_wl + num_wl_per_sram - 1); /* Outputs */ } fprintf(fp, ");\n"); // /* Update the counter */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + 1); update_sram_orgz_info_num_blwl(cur_sram_orgz_info, cur_bl + 1, cur_wl + 1); break; case SPICE_SRAM_STANDALONE: /* SRAM subckts*/ fprintf(fp, "%s %s_%d_ (", cur_sram_verilog_model->name, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, cur_sram_verilog_model, FALSE, TRUE)) { fprintf(fp, ",\n"); } fprintf(fp, "%s_out[%d], ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Input*/ fprintf(fp, "%s_out[%d], %s_outb[%d] ", cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Outputs */ fprintf(fp, ");\n"); // /* Update the counter */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + 1); break; case SPICE_SRAM_SCAN_CHAIN: /* Add a scan-chain DFF module here ! */ fprintf(fp, "%s %s_%d_ (", cur_sram_verilog_model->name, cur_sram_verilog_model->prefix, cur_sram_verilog_model->cnt); /* Only dump the global ports belonging to a spice_model */ if (0 < rec_dump_verilog_spice_model_global_ports(fp, cur_sram_verilog_model, FALSE, TRUE)) { fprintf(fp, ",\n"); } /* Input of Scan-chain DFF, should be connected to the output of its precedent */ dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram, 0, VERILOG_PORT_CONKT); fprintf(fp, ", \n"); // /* Output of Scan-chain DFF, should be connected to the output of its successor */ dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram, 1, VERILOG_PORT_CONKT); fprintf(fp, ", \n"); // /* Memory outputs of Scan-chain DFF, should be connected to the SRAM(memory port) of IOPAD, MUX and LUT */ dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram, 1, VERILOG_PORT_CONKT); fprintf(fp, ");\n"); // /* Update the counter */ update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + 1); break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n", __FILE__, __LINE__); exit(1); } /* Update the counter */ cur_sram_verilog_model->cnt++; return; } void dump_verilog_scff_config_bus(FILE* fp, t_spice_model* mem_spice_model, t_sram_orgz_info* cur_sram_orgz_info, int lsb, int msb, enum e_dump_verilog_port_type dump_port_type) { char* port_full_name = NULL; /* Check */ assert(NULL != mem_spice_model); assert(SPICE_MODEL_SCFF == mem_spice_model->type); /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /*Malloc and generate the full name of port */ port_full_name = (char*)my_malloc(sizeof(char)* ( strlen(mem_spice_model->prefix) + 1 + strlen(my_itoa(mem_spice_model->cnt)) + 12 + 1)); sprintf(port_full_name, "%s_%d_config_bus0", mem_spice_model->prefix, mem_spice_model->cnt); dump_verilog_generic_port(fp, dump_port_type, port_full_name, lsb, msb); /* Free */ /* Local variables such as port1_name and port2 name are automatically freed */ my_free(port_full_name); return; } /* Dump MUX reserved and normal configuration wire bus */ void dump_verilog_mem_config_bus(FILE* fp, t_spice_model* mem_spice_model, t_sram_orgz_info* cur_sram_orgz_info, int cur_num_sram, int num_mem_reserved_conf_bits, int num_mem_conf_bits) { int num_blb_ports, num_wlb_ports; t_spice_model_port** blb_port = NULL; t_spice_model_port** wlb_port = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Check */ assert(NULL != mem_spice_model); assert((SPICE_MODEL_SRAM == mem_spice_model->type) || (SPICE_MODEL_SCFF == mem_spice_model->type)); /* Depend on the style of configuraion circuit */ switch (cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: break; case SPICE_SRAM_SCAN_CHAIN: /* We do not need any configuration bus * Scan-chain FF outputs are directly wired to SRAM inputs of MUXes dump_verilog_scff_config_bus(fp, mem_spice_model, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mem_conf_bits - 1, VERILOG_PORT_WIRE); fprintf(fp, ";\n"); */ break; case SPICE_SRAM_MEMORY_BANK: /* Find the BLB and WLB port, if there is any */ find_blb_wlb_ports_spice_model(mem_spice_model, &num_blb_ports, &blb_port, &num_wlb_ports, &wlb_port); /* configuration wire bus */ if (0 < (num_mem_reserved_conf_bits + num_mem_conf_bits)) { /* First bus is for sram_out in CMOS MUX or BL in RRAM MUX */ fprintf(fp, "wire [%d:%d] %s_%d_configbus0;\n", cur_num_sram, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1, mem_spice_model->prefix, mem_spice_model->cnt); /* Second bus is for sram_out_inv in CMOS MUX or WL in RRAM MUX */ fprintf(fp, "wire [%d:%d] %s_%d_configbus1;\n", cur_num_sram, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1, mem_spice_model->prefix, mem_spice_model->cnt); if (1 == num_blb_ports) { fprintf(fp, "wire [%d:%d] %s_%d_configbus0_b;\n", cur_num_sram, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1, mem_spice_model->prefix, mem_spice_model->cnt); } if (1 == num_wlb_ports) { fprintf(fp, "wire [%d:%d] %s_%d_configbus1_b;\n", cur_num_sram, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1, mem_spice_model->prefix, mem_spice_model->cnt); } } /* Connect wires to config bus */ /* reserved configuration bits */ if (0 < num_mem_reserved_conf_bits) { fprintf(fp, "assign %s_%d_configbus0[%d:%d] = ", mem_spice_model->prefix, mem_spice_model->cnt, cur_num_sram, cur_num_sram + num_mem_reserved_conf_bits - 1); dump_verilog_reserved_sram_one_port(fp, cur_sram_orgz_info, 0, num_mem_reserved_conf_bits - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); fprintf(fp, "assign %s_%d_configbus1[%d:%d] = ", mem_spice_model->prefix, mem_spice_model->cnt, cur_num_sram, cur_num_sram + num_mem_reserved_conf_bits - 1); dump_verilog_reserved_sram_one_port(fp, cur_sram_orgz_info, 0, num_mem_reserved_conf_bits - 1, 1, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); } /* normal configuration bits */ if (0 < num_mem_conf_bits) { fprintf(fp, "assign %s_%d_configbus0[%d:%d] = ", mem_spice_model->prefix, mem_spice_model->cnt, cur_num_sram + num_mem_reserved_conf_bits, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mem_conf_bits - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); fprintf(fp, "assign %s_%d_configbus1[%d:%d] = ", mem_spice_model->prefix, mem_spice_model->cnt, cur_num_sram + num_mem_reserved_conf_bits, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mem_conf_bits - 1, 1, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); /* Dump inverted config_bus if needed */ if (1 == num_blb_ports) { fprintf(fp, "assign %s_%d_configbus0_b[%d:%d] = ", mem_spice_model->prefix, mem_spice_model->cnt, cur_num_sram + num_mem_reserved_conf_bits, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mem_conf_bits - 1, 2, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); } if (1 == num_wlb_ports) { fprintf(fp, "assign %s_%d_configbus1_b[%d:%d] = ", mem_spice_model->prefix, mem_spice_model->cnt, cur_num_sram + num_mem_reserved_conf_bits, cur_num_sram + num_mem_reserved_conf_bits + num_mem_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mem_conf_bits - 1, 3, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); } } break; default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n", __FILE__, __LINE__); exit(1); } return; } /* Dump MUX reserved and normal configuration wire bus */ void dump_verilog_cmos_mux_config_bus(FILE* fp, t_spice_model* mux_spice_model, t_sram_orgz_info* cur_sram_orgz_info, int mux_size, int cur_num_sram, int num_mux_reserved_conf_bits, int num_mux_conf_bits) { int num_blb_ports, num_wlb_ports; t_spice_model_port** blb_port = NULL; t_spice_model_port** wlb_port = NULL; t_spice_model* cur_sram_verilog_model = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Check */ assert(NULL != mux_spice_model); assert(SPICE_MODEL_MUX == mux_spice_model->type); switch(cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: break; case SPICE_SRAM_SCAN_CHAIN: /* We do not need any configuration bus * Scan-chain FF outputs are directly wired to SRAM inputs of MUXes */ dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, mux_spice_model, mux_size, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 1, VERILOG_PORT_WIRE); fprintf(fp, ";\n"); break; case SPICE_SRAM_MEMORY_BANK: /* configuration wire bus */ /* First bus is for sram_out in CMOS MUX */ fprintf(fp, "wire [%d:%d] %s_size%d_%d_configbus0;\n", cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, mux_spice_model->prefix, mux_size, mux_spice_model->cnt); /* Second bus is for sram_out_inv in CMOS MUX */ fprintf(fp, "wire [%d:%d] %s_size%d_%d_configbus1;\n", cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, mux_spice_model->prefix, mux_size, mux_spice_model->cnt); /* Declare output ports as wires */ dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, mux_spice_model, mux_size, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 0, VERILOG_PORT_WIRE); fprintf(fp, ";\n"); /* Declare output ports as wires */ dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, mux_spice_model, mux_size, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 1, VERILOG_PORT_WIRE); fprintf(fp, ";\n"); /* Connect wires to config bus */ fprintf(fp, "assign %s_size%d_%d_configbus0[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); fprintf(fp, "assign %s_size%d_%d_configbus1[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 1, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); /* Find the BLB and WLB port, if there is any */ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &cur_sram_verilog_model); find_blb_wlb_ports_spice_model(cur_sram_verilog_model, &num_blb_ports, &blb_port, &num_wlb_ports, &wlb_port); /* Dump inverted config_bus if needed */ if (1 == num_blb_ports) { fprintf(fp, "wire [%d:%d] %s_size%d_%d_configbus0_b;\n", cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, mux_spice_model->prefix, mux_size, mux_spice_model->cnt); fprintf(fp, "assign %s_size%d_%d_configbus0_b[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 2, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); } if (1 == num_wlb_ports) { fprintf(fp, "wire [%d:%d] %s_size%d_%d_configbus1_b;\n", cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, mux_spice_model->prefix, mux_size, mux_spice_model->cnt); fprintf(fp, "assign %s_size%d_%d_configbus1_b[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 3, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid SRAM organization!\n", __FILE__, __LINE__); exit(1); } return; } /* Dump MUX reserved and normal configuration wire bus */ void dump_verilog_mux_config_bus(FILE* fp, t_spice_model* mux_spice_model, t_sram_orgz_info* cur_sram_orgz_info, int mux_size, int cur_num_sram, int num_mux_reserved_conf_bits, int num_mux_conf_bits) { /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Check */ assert(NULL != mux_spice_model); assert(SPICE_MODEL_MUX == mux_spice_model->type); /* depend on the design technology of this MUX: * bus connections are different * SRAM MUX: bus is connected to the output ports of SRAM * RRAM MUX: bus is connected to the BL/WL of MUX * TODO: Maybe things will become even more complicated, * the bus connections may depend on the type of configuration circuit... * Currently, this is fine. */ switch (mux_spice_model->design_tech) { case SPICE_MODEL_DESIGN_CMOS: dump_verilog_cmos_mux_config_bus(fp, mux_spice_model, cur_sram_orgz_info, mux_size, cur_num_sram, num_mux_reserved_conf_bits, num_mux_conf_bits); break; case SPICE_MODEL_DESIGN_RRAM: /* configuration wire bus */ /* First bus is for sram_out in CMOS MUX or BL in RRAM MUX */ fprintf(fp, "wire [0:%d] %s_size%d_%d_configbus0;\n", num_mux_reserved_conf_bits + num_mux_conf_bits - 1, mux_spice_model->prefix, mux_size, mux_spice_model->cnt); /* Second bus is for sram_out_inv in CMOS MUX or WL in RRAM MUX */ fprintf(fp, "wire [0:%d] %s_size%d_%d_configbus1;\n", num_mux_reserved_conf_bits + num_mux_conf_bits - 1, mux_spice_model->prefix, mux_size, mux_spice_model->cnt); /* Connect wires to config bus */ /* reserved configuration bits */ if (0 < num_mux_reserved_conf_bits) { fprintf(fp, "assign %s_size%d_%d_configbus0[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, 0, num_mux_reserved_conf_bits - 1); dump_verilog_reserved_sram_one_port(fp, cur_sram_orgz_info, 0, num_mux_reserved_conf_bits - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); fprintf(fp, "assign %s_size%d_%d_configbus1[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, 0, num_mux_reserved_conf_bits - 1); dump_verilog_reserved_sram_one_port(fp, cur_sram_orgz_info, 0, num_mux_reserved_conf_bits - 1, 1, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); } /* normal configuration bits */ if (0 < num_mux_conf_bits) { fprintf(fp, "assign %s_size%d_%d_configbus0[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, num_mux_reserved_conf_bits, num_mux_reserved_conf_bits + num_mux_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); fprintf(fp, "assign %s_size%d_%d_configbus1[%d:%d] = ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt, num_mux_reserved_conf_bits, num_mux_reserved_conf_bits + num_mux_conf_bits - 1); dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 1, VERILOG_PORT_CONKT); fprintf(fp, ";\n"); } break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology for SRAM!\n", __FILE__, __LINE__); exit(1); } return; } /* Dump CMOS verilog MUX configuraiton bus ports */ void dump_verilog_cmos_mux_config_bus_ports(FILE* fp, t_spice_model* mux_spice_model, t_sram_orgz_info* cur_sram_orgz_info, int mux_size, int cur_num_sram, int num_mux_reserved_conf_bits, int num_mux_conf_bits) { /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Check */ assert(NULL != mux_spice_model); assert(SPICE_MODEL_MUX == mux_spice_model->type); switch(cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: break; case SPICE_SRAM_SCAN_CHAIN: /* configuration wire bus */ /* FOR Scan-chain, we need regular output of a scan-chain FF * We do not need a prefix implying MUX name, size and index */ dump_verilog_sram_one_port(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 1, VERILOG_PORT_CONKT); fprintf(fp, ",\n"); dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, mux_spice_model, mux_size, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 1, VERILOG_PORT_CONKT); break; case SPICE_SRAM_MEMORY_BANK: /* configuration wire bus */ /* First bus is for sram_out in CMOS MUX * We need a prefix implying MUX name, size and index */ dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, mux_spice_model, mux_size, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 0, VERILOG_PORT_CONKT); fprintf(fp, ",\n"); dump_verilog_mux_sram_one_outport(fp, cur_sram_orgz_info, mux_spice_model, mux_size, cur_num_sram, cur_num_sram + num_mux_conf_bits - 1, 1, VERILOG_PORT_CONKT); break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid SRAM organization!\n", __FILE__, __LINE__); exit(1); } return; } /* Dump MUX reserved and normal configuration wire bus */ void dump_verilog_mux_config_bus_ports(FILE* fp, t_spice_model* mux_spice_model, t_sram_orgz_info* cur_sram_orgz_info, int mux_size, int cur_num_sram, int num_mux_reserved_conf_bits, int num_mux_conf_bits) { /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Check */ assert(NULL != mux_spice_model); assert(SPICE_MODEL_MUX == mux_spice_model->type); /* depend on the design technology of this MUX: * bus connections are different * SRAM MUX: bus is connected to the output ports of SRAM */ switch (mux_spice_model->design_tech) { case SPICE_MODEL_DESIGN_CMOS: dump_verilog_cmos_mux_config_bus_ports(fp, mux_spice_model, cur_sram_orgz_info, mux_size, cur_num_sram, num_mux_reserved_conf_bits, num_mux_conf_bits); break; case SPICE_MODEL_DESIGN_RRAM: /* configuration wire bus */ fprintf(fp, "%s_size%d_%d_configbus0, ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt); fprintf(fp, "%s_size%d_%d_configbus1 ", mux_spice_model->prefix, mux_size, mux_spice_model->cnt); break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology for SRAM!\n", __FILE__, __LINE__); exit(1); } return; } /* Dump common ports of each pb_type in physical mode, * common ports include: * 1. inpad; 2. outpad; 3. iopad; TODO: merge other two to iopad * 4. SRAMs (standalone) * 5. BL/WLs * 6. Scan-chain FFs */ void dump_verilog_grid_common_port(FILE* fp, t_spice_model* cur_verilog_model, char* general_port_prefix, int lsb, int msb, enum e_dump_verilog_port_type dump_port_type) { char* port_full_name = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } assert(NULL != cur_verilog_model); if (0 > msb- lsb) { return; } /*Malloc and generate the full name of port */ port_full_name = (char*)my_malloc(sizeof(char)*(strlen(general_port_prefix) + strlen(cur_verilog_model->prefix) + 1)); sprintf(port_full_name, "%s%s", general_port_prefix, cur_verilog_model->prefix); fprintf(fp, ",\n"); dump_verilog_generic_port(fp, dump_port_type, port_full_name, msb, lsb); /* Free */ /* Local variables such as port1_name and port2 name are automatically freed */ my_free(port_full_name); return; } /* A widely used function to dump the configuration bus * This is supposed to be called when declaring local wires in the main body of a module * We will the internal wires (bus) used for connect SRAMs/RRAMs to other modules, * such as LUTs, MUXes and IOs */ void dump_verilog_sram_config_bus_internal_wires(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info, int lsb, int msb) { t_spice_model* mem_model = NULL; /* Get the memory spice model*/ get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model); assert (NULL != mem_model); /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Depend on the configuraion style */ switch(cur_sram_orgz_info->type) { case SPICE_SRAM_STANDALONE: break; case SPICE_SRAM_SCAN_CHAIN: dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, lsb, msb, 1, VERILOG_PORT_WIRE); fprintf(fp, ";\n"); break; case SPICE_SRAM_MEMORY_BANK: dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, lsb, msb, 0, VERILOG_PORT_WIRE); fprintf(fp, ";\n"); dump_verilog_sram_one_outport(fp, cur_sram_orgz_info, lsb, msb, 1, VERILOG_PORT_WIRE); fprintf(fp, ";\n"); break; default: vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid SRAM organization!\n", __FILE__, __LINE__); exit(1); } return; } void dump_verilog_toplevel_one_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type, int pin_index, int side, int x, int y, boolean dump_port_type) { int height; t_type_ptr type = NULL; char* verilog_port_type = NULL; /* Check the file handler*/ if (NULL == fp) { vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n", __FILE__, __LINE__); exit(1); } /* Check */ assert((!(0 > x))&&(!(x > (nx + 1)))); assert((!(0 > y))&&(!(y > (ny + 1)))); type = grid[x][y].type; assert(NULL != type); assert((!(0 > pin_index))&&(pin_index < type->num_pins)); assert((!(0 > side))&&(!(side > 3))); /* Assign the type of PIN*/ switch (pin_type) { case IPIN: /* case SINK: */ verilog_port_type = "output"; break; /* case SOURCE: */ case OPIN: verilog_port_type = "input"; break; /* SINK and SOURCE are hypothesis nodes */ default: vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid pin_type!\n", __FILE__, __LINE__); exit(1); } /* Output the pins on the side*/ height = get_grid_pin_height(x, y, pin_index); if (1 == type->pinloc[height][side][pin_index]) { /* Not sure if we need to plus a height */ /* fprintf(fp, "grid_%d__%d__pin_%d__%d__%d_ ", x, y, height, side, pin_index); */ if (TRUE == dump_port_type) { fprintf(fp, "%s ", verilog_port_type); } fprintf(fp, " grid_%d__%d__pin_%d__%d__%d_", x, y, height, side, pin_index); if (TRUE == dump_port_type) { fprintf(fp, ",\n"); } } else { vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Fail to print a grid pin (x=%d, y=%d, height=%d, side=%d, index=%d)\n", __FILE__, __LINE__, x, y, height, side, pin_index); exit(1); } return; }