14f24fc9aSDan Tang#! /usr/bin/env python3 2885733f1SZihao Yu 3885733f1SZihao Yu# See LICENSE.SiFive for license details. 4885733f1SZihao Yu# See LICENSE.Berkeley for license details. 5885733f1SZihao Yu 6885733f1SZihao Yuimport sys 7885733f1SZihao Yuimport math 8885733f1SZihao Yu 9885733f1SZihao Yuuse_latches = 0 10885733f1SZihao Yu 114f24fc9aSDan Tangclass VerilogModuleGenerator(object): 124f24fc9aSDan Tang def __init__(self, name): 134f24fc9aSDan Tang self.name = name 144f24fc9aSDan Tang self.port_spec = [] 154f24fc9aSDan Tang self.decl = [] 164f24fc9aSDan Tang self.combinational = [] 174f24fc9aSDan Tang self.sequential = [] 184f24fc9aSDan Tang 194f24fc9aSDan Tang def __format_width(self, width): 204f24fc9aSDan Tang return "[{}:0] ".format(width-1) if width > 1 else "" 214f24fc9aSDan Tang 224f24fc9aSDan Tang def __format_depth(self, depth): 234f24fc9aSDan Tang return " [{}:0]".format(depth-1) if depth > 1 else "" 244f24fc9aSDan Tang 254f24fc9aSDan Tang def add_io(self, io_type, width, name): 264f24fc9aSDan Tang width_str = self.__format_width(width) 274f24fc9aSDan Tang # print(io_type, width_str, name) 284f24fc9aSDan Tang self.port_spec.append(f'{io_type} {width_str}{name}') 294f24fc9aSDan Tang 304f24fc9aSDan Tang def add_input(self, width, name): 314f24fc9aSDan Tang self.add_io("input", width, name) 324f24fc9aSDan Tang 334f24fc9aSDan Tang def add_output(self, width, name): 344f24fc9aSDan Tang self.add_io("output", width, name) 354f24fc9aSDan Tang 364f24fc9aSDan Tang def add_decl(self, decl_type, width, name, depth=1): 374f24fc9aSDan Tang width_str = self.__format_width(width) 384f24fc9aSDan Tang depth_str = self.__format_depth(depth) 394f24fc9aSDan Tang self.decl.append(f"{decl_type} {width_str}{name}{depth_str};") 404f24fc9aSDan Tang 414f24fc9aSDan Tang def add_decl_reg(self, width, name, depth=1): 424f24fc9aSDan Tang self.add_decl("reg", width, name, depth) 434f24fc9aSDan Tang 444f24fc9aSDan Tang def add_decl_wire(self, width, name, depth=1): 454f24fc9aSDan Tang self.add_decl("wire", width, name, depth) 464f24fc9aSDan Tang 474f24fc9aSDan Tang def add_decl_line(self, line): 484f24fc9aSDan Tang self.decl.append(line) 494f24fc9aSDan Tang 504f24fc9aSDan Tang def add_sequential(self, line): 514f24fc9aSDan Tang self.sequential.append(line) 524f24fc9aSDan Tang 534f24fc9aSDan Tang def add_combinational(self, line): 544f24fc9aSDan Tang self.combinational.append(line) 554f24fc9aSDan Tang 564f24fc9aSDan Tang def generate(self, blackbox): 574f24fc9aSDan Tang body = "\ 584f24fc9aSDan Tang %s\n\ 594f24fc9aSDan Tang %s\n\ 604f24fc9aSDan Tang %s\n" % ('\n '.join(self.decl), '\n '.join(self.sequential), '\n '.join(self.combinational)) 614f24fc9aSDan Tang 624f24fc9aSDan Tang s = "\nmodule %s(\n\ 634f24fc9aSDan Tang %s\n\ 644f24fc9aSDan Tang);\n\ 654f24fc9aSDan Tang\n\ 664f24fc9aSDan Tang%s\ 674f24fc9aSDan Tang\n\ 684f24fc9aSDan Tangendmodule" % (self.name, ',\n '.join(self.port_spec), body if not blackbox else blackbox) 694f24fc9aSDan Tang return s 704f24fc9aSDan Tang 714f24fc9aSDan Tang 724f24fc9aSDan Tangclass Reshaper(object): 734f24fc9aSDan Tang def __init__(self, before, after): 744f24fc9aSDan Tang # print(before, after) 754f24fc9aSDan Tang self.conf = before 764f24fc9aSDan Tang self.new_conf = after 774f24fc9aSDan Tang assert(self.conf[-1] == ['write', 'read']) 784f24fc9aSDan Tang assert(self.new_conf[-1] == ['mwrite', 'read']) 794f24fc9aSDan Tang 804f24fc9aSDan Tang def generate(self, mem): 814f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 824f24fc9aSDan Tang (new_name, new_width, new_depth, new_mask_gran, new_mask_seg, _) = self.new_conf 834f24fc9aSDan Tang addr_bits = math.log2(depth) 844f24fc9aSDan Tang ways = new_width // width 854f24fc9aSDan Tang ways_bits = int(math.log2(ways)) 864f24fc9aSDan Tang mem.add_decl_wire(new_width, "data_read") 874f24fc9aSDan Tang mem.add_decl_wire(new_width, "data_write") 884f24fc9aSDan Tang mem.add_combinational(f"assign data_write = ") 894f24fc9aSDan Tang sels = [f"{f'(write_way_index == {w}) ?' if w != ways-1 else ''} ({{{new_width-width}'h0, W0_data}} << {width*w})" for w in range(ways)] 904f24fc9aSDan Tang mem.add_combinational(":\n ".join(sels) + ";") 914f24fc9aSDan Tang mem.add_decl_wire(ways_bits, "read_way_index") 924f24fc9aSDan Tang mem.add_combinational(f"assign read_way_index = R0_addr[{ways_bits-1}:0];") 934f24fc9aSDan Tang mem.add_decl_wire(ways_bits, "write_way_index") 944f24fc9aSDan Tang mem.add_combinational(f"assign write_way_index = W0_addr[{ways_bits-1}:0];") 954f24fc9aSDan Tang mem.add_combinational(f"{new_name} array (") 964f24fc9aSDan Tang mem.add_combinational(f" .W0_clk(W0_clk),") 974f24fc9aSDan Tang mem.add_combinational(f" .W0_addr(W0_addr[{new_width-1}:{ways_bits}]),") 984f24fc9aSDan Tang mem.add_combinational(f" .W0_en(W0_en),") 994f24fc9aSDan Tang mem.add_combinational(f" .W0_data(data_write),") 1004f24fc9aSDan Tang mem.add_combinational(f" .W0_mask({ways}'h1 << write_way_index),") 1014f24fc9aSDan Tang mem.add_combinational(f" .R0_clk(R0_clk),") 1024f24fc9aSDan Tang mem.add_combinational(f" .R0_addr(R0_addr[{new_width-1}:{ways_bits}]),") 1034f24fc9aSDan Tang mem.add_combinational(f" .R0_en(R0_en),") 1044f24fc9aSDan Tang mem.add_combinational(f" .R0_data(data_read)") 1054f24fc9aSDan Tang mem.add_combinational(f");") 1064f24fc9aSDan Tang mem.add_combinational(f"assign R0_data = ") 1074f24fc9aSDan Tang sels = [f"{f'(read_way_index == {w}) ?' if w != ways-1 else ''} data_read[{width*(w+1)-1}:{width*w}]" for w in range(ways)] 1084f24fc9aSDan Tang mem.add_combinational(":\n ".join(sels) + ";") 1094f24fc9aSDan Tang 1104f24fc9aSDan Tang 1114f24fc9aSDan Tangclass Spliter(object): 1124f24fc9aSDan Tang def __init__(self, before, after): 1134f24fc9aSDan Tang # print(before, after) 1144f24fc9aSDan Tang self.conf = before 1154f24fc9aSDan Tang self.new_conf = after 1164f24fc9aSDan Tang assert(self.conf[-1] == ['mrw']) 1174f24fc9aSDan Tang assert(self.new_conf[-1] == ['rw']) 1184f24fc9aSDan Tang 1194f24fc9aSDan Tang def generate(self, mem): 1204f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 1214f24fc9aSDan Tang (new_name, new_width, new_depth, new_mask_gran, new_mask_seg, _) = self.new_conf 1224f24fc9aSDan Tang assert(depth == new_depth) 1234f24fc9aSDan Tang ways = width // new_width 1244f24fc9aSDan Tang for i in range(ways): 1254f24fc9aSDan Tang data_slice = f"[{new_width*(i+1)-1}:{new_width*i}]" 1264f24fc9aSDan Tang mem.add_combinational(f"{new_name} array_{i} (") 1274f24fc9aSDan Tang mem.add_combinational(f" .RW0_clk(RW0_clk),") 1284f24fc9aSDan Tang mem.add_combinational(f" .RW0_addr(RW0_addr),") 1294f24fc9aSDan Tang mem.add_combinational(f" .RW0_en(RW0_en),") 1304f24fc9aSDan Tang mem.add_combinational(f" .RW0_wmode(RW0_wmode && RW0_wmask[{i}]),") 1314f24fc9aSDan Tang mem.add_combinational(f" .RW0_wdata(RW0_wdata{data_slice}),") 1324f24fc9aSDan Tang mem.add_combinational(f" .RW0_rdata(RW0_rdata{data_slice})") 1334f24fc9aSDan Tang mem.add_combinational(f");") 1344f24fc9aSDan Tang 1354f24fc9aSDan Tangclass SRAM(object): 1364f24fc9aSDan Tang def __init__(self, line): 1374f24fc9aSDan Tang self.parse_line(line) 1384f24fc9aSDan Tang self.prepare_module() 1394f24fc9aSDan Tang 1404f24fc9aSDan Tang def parse_line(self, line): 141885733f1SZihao Yu name = '' 142885733f1SZihao Yu width = 0 143885733f1SZihao Yu depth = 0 144885733f1SZihao Yu ports = '' 145885733f1SZihao Yu mask_gran = 0 146885733f1SZihao Yu tokens = line.split() 147885733f1SZihao Yu i = 0 148885733f1SZihao Yu for i in range(0, len(tokens), 2): 149885733f1SZihao Yu s = tokens[i] 150885733f1SZihao Yu if s == 'name': 151885733f1SZihao Yu name = tokens[i+1] 152885733f1SZihao Yu elif s == 'width': 153885733f1SZihao Yu width = int(tokens[i+1]) 154885733f1SZihao Yu mask_gran = width # default setting 155885733f1SZihao Yu elif s == 'depth': 156885733f1SZihao Yu depth = int(tokens[i+1]) 157885733f1SZihao Yu elif s == 'ports': 158885733f1SZihao Yu ports = tokens[i+1].split(',') 159885733f1SZihao Yu elif s == 'mask_gran': 160885733f1SZihao Yu mask_gran = int(tokens[i+1]) 161885733f1SZihao Yu else: 1624f24fc9aSDan Tang sys.exit('%s: unknown argument %s' % (sys.argv[0], i)) 1634f24fc9aSDan Tang self.conf = (name, width, depth, mask_gran, width//mask_gran, ports) 1644f24fc9aSDan Tang # return (name, width, depth, mask_gran, width//mask_gran, ports) 165885733f1SZihao Yu 1664f24fc9aSDan Tang def prepare_module(self): 1674f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 168885733f1SZihao Yu addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 1694f24fc9aSDan Tang 1704f24fc9aSDan Tang mem = VerilogModuleGenerator(name) 171885733f1SZihao Yu readports = [] 172885733f1SZihao Yu writeports = [] 173885733f1SZihao Yu latchports = [] 174885733f1SZihao Yu rwports = [] 175885733f1SZihao Yu maskedports = {} 1764f24fc9aSDan Tang 1774f24fc9aSDan Tang for pid, ptype in enumerate(ports): 178885733f1SZihao Yu if ptype[0:1] == 'm': 179885733f1SZihao Yu ptype = ptype[1:] 180885733f1SZihao Yu maskedports[pid] = pid 181885733f1SZihao Yu 182885733f1SZihao Yu if ptype == 'read': 183885733f1SZihao Yu prefix = 'R%d_' % len(readports) 1844f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 1854f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 1864f24fc9aSDan Tang mem.add_input(1, prefix + "en") 1874f24fc9aSDan Tang mem.add_output(width, prefix + "data") 188885733f1SZihao Yu readports.append(pid) 189885733f1SZihao Yu elif ptype == 'write': 190885733f1SZihao Yu prefix = 'W%d_' % len(writeports) 1914f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 1924f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 1934f24fc9aSDan Tang mem.add_input(1, prefix + "en") 1944f24fc9aSDan Tang mem.add_input(width, prefix + "data") 195885733f1SZihao Yu if pid in maskedports: 1964f24fc9aSDan Tang mem.add_input(mask_seg, prefix + "mask") 197885733f1SZihao Yu if not use_latches or pid in maskedports: 198885733f1SZihao Yu writeports.append(pid) 199885733f1SZihao Yu else: 200885733f1SZihao Yu latchports.append(pid) 201885733f1SZihao Yu elif ptype == 'rw': 202885733f1SZihao Yu prefix = 'RW%d_' % len(rwports) 2034f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 2044f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 2054f24fc9aSDan Tang mem.add_input(1, prefix + "en") 2064f24fc9aSDan Tang mem.add_input(1, prefix + "wmode") 207885733f1SZihao Yu if pid in maskedports: 2084f24fc9aSDan Tang mem.add_input(mask_seg, prefix + "wmask") 2094f24fc9aSDan Tang mem.add_input(width, prefix + "wdata") 2104f24fc9aSDan Tang mem.add_output(width, prefix + "rdata") 211885733f1SZihao Yu rwports.append(pid) 212885733f1SZihao Yu else: 213885733f1SZihao Yu sys.exit('%s: unknown port type %s' % (sys.argv[0], ptype)) 2144f24fc9aSDan Tang self.mem = mem 2154f24fc9aSDan Tang self.ports_conf = (readports, writeports, latchports, rwports, maskedports) 2164f24fc9aSDan Tang 2174f24fc9aSDan Tang def generate(self, blackbox): 2184f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 2194f24fc9aSDan Tang addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 2204f24fc9aSDan Tang mem, (readports, writeports, latchports, rwports, maskedports) = self.mem, self.ports_conf 221885733f1SZihao Yu 222885733f1SZihao Yu nr = len(readports) 223885733f1SZihao Yu nw = len(writeports) 224885733f1SZihao Yu nrw = len(rwports) 225885733f1SZihao Yu 226885733f1SZihao Yu def emit_read(idx, rw): 227885733f1SZihao Yu prefix = ('RW%d_' if rw else 'R%d_') % idx 228885733f1SZihao Yu data = ('%srdata' if rw else '%sdata') % prefix 229885733f1SZihao Yu en = ('%sen && !%swmode' % (prefix, prefix)) if rw else ('%sen' % prefix) 2304f24fc9aSDan Tang mem.add_decl_reg(1, f"reg_{prefix}ren") 2314f24fc9aSDan Tang mem.add_decl_reg(addr_width, f"reg_{prefix}addr") 2324f24fc9aSDan Tang mem.add_sequential(f"always @(posedge {prefix}clk)") 2334f24fc9aSDan Tang mem.add_sequential(f" reg_{prefix}ren <= {en};") 2344f24fc9aSDan Tang mem.add_sequential(f"always @(posedge {prefix}clk)") 2354f24fc9aSDan Tang mem.add_sequential(f" if ({en}) reg_{prefix}addr <= {prefix}addr;") 2364f24fc9aSDan Tang mem.add_combinational("`ifdef RANDOMIZE_GARBAGE_ASSIGN") 2374f24fc9aSDan Tang mem.add_combinational(f"reg [{((width-1)//32+1)*32-1}:0] {prefix}random;") 2384f24fc9aSDan Tang mem.add_combinational(f"`ifdef RANDOMIZE_MEM_INIT") 2394f24fc9aSDan Tang mem.add_combinational(f" initial begin") 2404f24fc9aSDan Tang mem.add_combinational(f" #`RANDOMIZE_DELAY begin end") 2414f24fc9aSDan Tang mem.add_combinational(' %srandom = {%s};' % (prefix, ', '.join(['$random'] * ((width-1)//32+1)))) 2424f24fc9aSDan Tang mem.add_combinational(' reg_%sren = %srandom[0];' % (prefix, prefix)) 2434f24fc9aSDan Tang mem.add_combinational(' end') 2444f24fc9aSDan Tang mem.add_combinational('`endif') 2454f24fc9aSDan Tang mem.add_combinational('always @(posedge %sclk) %srandom <= {%s};' % (prefix, prefix, ', '.join(['$random'] * ((width-1)//32+1)))) 2464f24fc9aSDan Tang mem.add_combinational('assign %s = reg_%sren ? ram[reg_%saddr] : %srandom[%d:0];' % (data, prefix, prefix, prefix, width-1)) 2474f24fc9aSDan Tang mem.add_combinational('`else') 2484f24fc9aSDan Tang mem.add_combinational('assign %s = ram[reg_%saddr];' % (data, prefix)) 2494f24fc9aSDan Tang mem.add_combinational('`endif') 250885733f1SZihao Yu 251885733f1SZihao Yu for idx in range(nr): 252885733f1SZihao Yu emit_read(idx, False) 253885733f1SZihao Yu 254885733f1SZihao Yu for idx in range(nrw): 255885733f1SZihao Yu emit_read(idx, True) 256885733f1SZihao Yu 257885733f1SZihao Yu for idx in range(len(latchports)): 258885733f1SZihao Yu prefix = 'W%d_' % idx 2594f24fc9aSDan Tang mem.add_decl_reg(addr_width, f"latch_{prefix}addr") 2604f24fc9aSDan Tang mem.add_decl_reg(width, f"latch_{prefix}data") 2614f24fc9aSDan Tang mem.add_decl_reg(1, f"latch_{prefix}en") 2624f24fc9aSDan Tang mem.add_combinational('always @(*) begin') 2634f24fc9aSDan Tang mem.add_combinational(' if (!%sclk && %sen) latch_%saddr <= %saddr;' % (prefix, prefix, prefix, prefix)) 2644f24fc9aSDan Tang mem.add_combinational(' if (!%sclk && %sen) latch_%sdata <= %sdata;' % (prefix, prefix, prefix, prefix)) 2654f24fc9aSDan Tang mem.add_combinational(' if (!%sclk) latch_%sen <= %sen;' % (prefix, prefix, prefix)) 2664f24fc9aSDan Tang mem.add_combinational('end') 2674f24fc9aSDan Tang mem.add_combinational('always @(*)') 2684f24fc9aSDan Tang mem.add_combinational(' if (%sclk && latch_%sen)' % (prefix, prefix)) 2694f24fc9aSDan Tang mem.add_combinational(' ram[latch_%saddr] <= latch_%sdata;' % (prefix, prefix)) 270885733f1SZihao Yu 2714f24fc9aSDan Tang mem.add_decl_reg(width, "ram", depth) 2724f24fc9aSDan Tang mem.add_decl_line('`ifdef RANDOMIZE_MEM_INIT') 2734f24fc9aSDan Tang mem.add_decl_line(' integer initvar;') 2744f24fc9aSDan Tang mem.add_decl_line(' initial begin') 2754f24fc9aSDan Tang mem.add_decl_line(' #`RANDOMIZE_DELAY begin end') 2764f24fc9aSDan Tang mem.add_decl_line(' for (initvar = 0; initvar < %d; initvar = initvar+1)' % depth) 2774f24fc9aSDan Tang mem.add_decl_line(' ram[initvar] = {%d {$random}};' % ((width-1)//32+1)) 278885733f1SZihao Yu for idx in range(nr): 279885733f1SZihao Yu prefix = 'R%d_' % idx 2804f24fc9aSDan Tang mem.add_decl_line(' reg_%saddr = {%d {$random}};' % (prefix, ((addr_width-1)//32+1))) 281885733f1SZihao Yu for idx in range(nrw): 282885733f1SZihao Yu prefix = 'RW%d_' % idx 2834f24fc9aSDan Tang mem.add_decl_line(' reg_%saddr = {%d {$random}};' % (prefix, ((addr_width-1)//32+1))) 2844f24fc9aSDan Tang mem.add_decl_line(' end') 2854f24fc9aSDan Tang mem.add_decl_line('`endif') 286885733f1SZihao Yu 2874f24fc9aSDan Tang mem.add_decl_line("integer i;") 288885733f1SZihao Yu for idx in range(nw): 289885733f1SZihao Yu prefix = 'W%d_' % idx 290885733f1SZihao Yu pid = writeports[idx] 2914f24fc9aSDan Tang mem.add_sequential('always @(posedge %sclk)' % prefix) 2924f24fc9aSDan Tang mem.add_sequential(" if (%sen) begin" % prefix) 293885733f1SZihao Yu for i in range(mask_seg): 294885733f1SZihao Yu mask = ('if (%smask[%d]) ' % (prefix, i)) if pid in maskedports else '' 295885733f1SZihao Yu ram_range = '%d:%d' % ((i+1)*mask_gran-1, i*mask_gran) 2964f24fc9aSDan Tang mem.add_sequential(" %sram[%saddr][%s] <= %sdata[%s];" % (mask, prefix, ram_range, prefix, ram_range)) 2974f24fc9aSDan Tang mem.add_sequential(" end") 298885733f1SZihao Yu for idx in range(nrw): 299885733f1SZihao Yu pid = rwports[idx] 300885733f1SZihao Yu prefix = 'RW%d_' % idx 3014f24fc9aSDan Tang mem.add_sequential('always @(posedge %sclk)' % prefix) 3024f24fc9aSDan Tang mem.add_sequential(" if (%sen && %swmode) begin" % (prefix, prefix)) 303885733f1SZihao Yu if mask_seg > 0: 3044f24fc9aSDan Tang mem.add_sequential(" for(i=0;i<%d;i=i+1) begin" % mask_seg) 305885733f1SZihao Yu if pid in maskedports: 3064f24fc9aSDan Tang mem.add_sequential(" if(%swmask[i]) begin" % prefix) 3074f24fc9aSDan Tang mem.add_sequential(" ram[%saddr][i*%d +: %d] <= %swdata[i*%d +: %d];" %(prefix, mask_gran, mask_gran, prefix, mask_gran, mask_gran)) 3084f24fc9aSDan Tang mem.add_sequential(" end") 309885733f1SZihao Yu else: 3104f24fc9aSDan Tang mem.add_sequential(" ram[%saddr][i*%d +: %d] <= %swdata[i*%d +: %d];" %(prefix, mask_gran, mask_gran, prefix, mask_gran, mask_gran)) 3114f24fc9aSDan Tang mem.add_sequential(" end") 3124f24fc9aSDan Tang mem.add_sequential(" end") 3134f24fc9aSDan Tang return mem.generate(blackbox) 314885733f1SZihao Yu 3154f24fc9aSDan Tang 3164f24fc9aSDan Tangclass SRAM_TSMC28(SRAM): 3174f24fc9aSDan Tang def __init__(self, line): 3184f24fc9aSDan Tang super().__init__(line) 3194f24fc9aSDan Tang self.sub_srams = [] 3204f24fc9aSDan Tang if self.__check_subsrams(): 3214f24fc9aSDan Tang print(line.strip()) 3224f24fc9aSDan Tang 3234f24fc9aSDan Tang def __check_subsrams(self): 3244f24fc9aSDan Tang need_split = self.__split() 3254f24fc9aSDan Tang need_reshape = self.__reshape() 3264f24fc9aSDan Tang assert(not (need_split and need_reshape)) 3274f24fc9aSDan Tang return not need_split and not need_reshape 3284f24fc9aSDan Tang 3294f24fc9aSDan Tang def __split(self): 3304f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 331*eae78b10SYinan Xu '''if ports == ["mrw"] and mask_gran >= 32: 3324f24fc9aSDan Tang new_conf = (name + "_sub", str(depth), str(mask_gran), "rw") 3334f24fc9aSDan Tang line_field = ("name", "depth", "width", "ports") 3344f24fc9aSDan Tang new_line = " ".join(map(lambda x: " ".join(x), zip(line_field, new_conf))) 3354f24fc9aSDan Tang new_sram = SRAM_TSMC28(new_line) 3364f24fc9aSDan Tang self.sub_srams.append(new_sram) 3374f24fc9aSDan Tang reshaper = Spliter(self.conf, new_sram.conf) 3384f24fc9aSDan Tang reshaper.generate(self.mem) 339*eae78b10SYinan Xu return True''' 3404f24fc9aSDan Tang return False 3414f24fc9aSDan Tang 3424f24fc9aSDan Tang def __reshape(self): 3434f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 3444f24fc9aSDan Tang if width == 2 and depth == 256: 3454f24fc9aSDan Tang new_conf = (name + "_sub", "64", "8", "mwrite,read", "2") 3464f24fc9aSDan Tang line_field = ("name", "depth", "width", "ports", "mask_gran") 3474f24fc9aSDan Tang new_line = " ".join(map(lambda x: " ".join(x), zip(line_field, new_conf))) 3484f24fc9aSDan Tang new_sram = SRAM_TSMC28(new_line) 3494f24fc9aSDan Tang self.sub_srams.append(new_sram) 3504f24fc9aSDan Tang reshaper = Reshaper(self.conf, new_sram.conf) 3514f24fc9aSDan Tang reshaper.generate(self.mem) 3524f24fc9aSDan Tang return True 3534f24fc9aSDan Tang return False 3544f24fc9aSDan Tang 3554f24fc9aSDan Tang def __get_tsmc_lib(self): 3564f24fc9aSDan Tang mem, (readports, writeports, latchports, rwports, maskedports) = self.mem, self.ports_conf 3574f24fc9aSDan Tang blackbox = "// tsmc lib here\n" 3584f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 3594f24fc9aSDan Tang nports = (len(readports), len(writeports), len(rwports)) 3604f24fc9aSDan Tang addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 3614f24fc9aSDan Tang masked = len(maskedports) > 0 3624f24fc9aSDan Tang # from tsmc28_sram import gen_tsmc_ram_1pw, gen_tsmc_ram_1pnw, gen_tsmc_ram_2pw, gen_tsmc_ram_2pnw 3634f24fc9aSDan Tang # if nports == (1, 1, 0): 3644f24fc9aSDan Tang # if masked: 3654f24fc9aSDan Tang # blackbox = gen_tsmc_ram_2pw("TS6N28HPCPLVTA64X8M2F", width, mask_gran) 3664f24fc9aSDan Tang # else: 3674f24fc9aSDan Tang # blackbox = gen_tsmc_ram_2pnw("TS6N28HPCPLVTA64X14M2F") 3684f24fc9aSDan Tang # elif nports == (0, 0, 1): 3694f24fc9aSDan Tang # if masked: 3704f24fc9aSDan Tang # blackbox = gen_tsmc_ram_1pw('TS1N28HPCPLVTB8192X64M8SW', width, mask_gran, addr_width) 3714f24fc9aSDan Tang # else: 3724f24fc9aSDan Tang # blackbox = gen_tsmc_ram_1pnw('TS5N28HPCPLVTA64X144M2F', width, addr_width) 3734f24fc9aSDan Tang # else: 3744f24fc9aSDan Tang # blackbox = "// unknown tsmc lib type\n" 3754f24fc9aSDan Tang return mem.generate(blackbox) 3764f24fc9aSDan Tang 3774f24fc9aSDan Tang def generate(self, blackbox, itself_only=False): 3784f24fc9aSDan Tang if itself_only: 3794f24fc9aSDan Tang # generate splits or reshapes 3804f24fc9aSDan Tang if self.sub_srams: 3814f24fc9aSDan Tang return self.mem.generate("") 3824f24fc9aSDan Tang # use empty blackbox 3834f24fc9aSDan Tang elif blackbox: 3844f24fc9aSDan Tang return super().generate(" ") 3854f24fc9aSDan Tang # insert tsmc libs 3864f24fc9aSDan Tang else: 3874f24fc9aSDan Tang return self.__get_tsmc_lib() 3884f24fc9aSDan Tang else: 3894f24fc9aSDan Tang s = self.generate(blackbox, True) 3904f24fc9aSDan Tang for sram in self.sub_srams: 3914f24fc9aSDan Tang s += sram.generate(blackbox) 392885733f1SZihao Yu return s 393885733f1SZihao Yu 3944f24fc9aSDan Tang 395885733f1SZihao Yudef main(args): 396885733f1SZihao Yu f = open(args.output_file, "w") if (args.output_file) else None 397885733f1SZihao Yu conf_file = args.conf 398885733f1SZihao Yu for line in open(conf_file): 3994f24fc9aSDan Tang sram = SRAM(line) 4004f24fc9aSDan Tang if args.tsmc28: 4014f24fc9aSDan Tang sram = SRAM_TSMC28(line) 402885733f1SZihao Yu else: 4034f24fc9aSDan Tang sram = SRAM(line) 4044f24fc9aSDan Tang if f is not None: 4054f24fc9aSDan Tang f.write(sram.generate(args.blackbox)) 4064f24fc9aSDan Tang else: 4074f24fc9aSDan Tang print(sram.generate(args.blackbox)) 4084f24fc9aSDan Tang 409885733f1SZihao Yu 410885733f1SZihao Yuif __name__ == '__main__': 411885733f1SZihao Yu import argparse 412885733f1SZihao Yu parser = argparse.ArgumentParser(description='Memory generator for Rocket Chip') 413885733f1SZihao Yu parser.add_argument('conf', metavar='.conf file') 4144f24fc9aSDan Tang parser.add_argument('--tsmc28', action='store_true', help='use tsmc28 sram to generate module body') 415885733f1SZihao Yu parser.add_argument('--blackbox', '-b', action='store_true', help='set to disable output of module body') 416885733f1SZihao Yu #parser.add_argument('--use_latches', '-l', action='store_true', help='set to enable use of latches') 417885733f1SZihao Yu parser.add_argument('--output_file', '-o', help='name of output file, default is stdout') 418885733f1SZihao Yu args = parser.parse_args() 419885733f1SZihao Yu #use_latches = args.use_latches 420885733f1SZihao Yu main(args) 421