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 4451e45dbbSTang Haojin def add_decl_ram(self, width, name, depth=1): 4551e45dbbSTang Haojin width_str = self.__format_width(width) 4651e45dbbSTang Haojin depth_str = " [{}:0]".format(depth-1) 4751e45dbbSTang Haojin self.decl.append(f"reg {width_str}{name}{depth_str};") 4851e45dbbSTang Haojin 494f24fc9aSDan Tang def add_decl_wire(self, width, name, depth=1): 504f24fc9aSDan Tang self.add_decl("wire", width, name, depth) 514f24fc9aSDan Tang 524f24fc9aSDan Tang def add_decl_line(self, line): 534f24fc9aSDan Tang self.decl.append(line) 544f24fc9aSDan Tang 554f24fc9aSDan Tang def add_sequential(self, line): 564f24fc9aSDan Tang self.sequential.append(line) 574f24fc9aSDan Tang 584f24fc9aSDan Tang def add_combinational(self, line): 594f24fc9aSDan Tang self.combinational.append(line) 604f24fc9aSDan Tang 614f24fc9aSDan Tang def generate(self, blackbox): 624f24fc9aSDan Tang body = "\ 634f24fc9aSDan Tang %s\n\ 644f24fc9aSDan Tang %s\n\ 654f24fc9aSDan Tang %s\n" % ('\n '.join(self.decl), '\n '.join(self.sequential), '\n '.join(self.combinational)) 664f24fc9aSDan Tang 674f24fc9aSDan Tang s = "\nmodule %s(\n\ 684f24fc9aSDan Tang %s\n\ 694f24fc9aSDan Tang);\n\ 704f24fc9aSDan Tang\n\ 714f24fc9aSDan Tang%s\ 724f24fc9aSDan Tang\n\ 734f24fc9aSDan Tangendmodule" % (self.name, ',\n '.join(self.port_spec), body if not blackbox else blackbox) 744f24fc9aSDan Tang return s 754f24fc9aSDan Tang 764f24fc9aSDan Tang 774f24fc9aSDan Tangclass Reshaper(object): 784f24fc9aSDan Tang def __init__(self, before, after): 794f24fc9aSDan Tang # print(before, after) 804f24fc9aSDan Tang self.conf = before 814f24fc9aSDan Tang self.new_conf = after 824f24fc9aSDan Tang assert(self.conf[-1] == ['write', 'read']) 834f24fc9aSDan Tang assert(self.new_conf[-1] == ['mwrite', 'read']) 844f24fc9aSDan Tang 854f24fc9aSDan Tang def generate(self, mem): 864f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 874f24fc9aSDan Tang (new_name, new_width, new_depth, new_mask_gran, new_mask_seg, _) = self.new_conf 884f24fc9aSDan Tang addr_bits = math.log2(depth) 894f24fc9aSDan Tang ways = new_width // width 904f24fc9aSDan Tang ways_bits = int(math.log2(ways)) 914f24fc9aSDan Tang mem.add_decl_wire(new_width, "data_read") 924f24fc9aSDan Tang mem.add_decl_wire(new_width, "data_write") 934f24fc9aSDan Tang mem.add_combinational(f"assign data_write = ") 944f24fc9aSDan 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)] 954f24fc9aSDan Tang mem.add_combinational(":\n ".join(sels) + ";") 964f24fc9aSDan Tang mem.add_decl_wire(ways_bits, "read_way_index") 974f24fc9aSDan Tang mem.add_combinational(f"assign read_way_index = R0_addr[{ways_bits-1}:0];") 984f24fc9aSDan Tang mem.add_decl_wire(ways_bits, "write_way_index") 994f24fc9aSDan Tang mem.add_combinational(f"assign write_way_index = W0_addr[{ways_bits-1}:0];") 1004f24fc9aSDan Tang mem.add_combinational(f"{new_name} array (") 1014f24fc9aSDan Tang mem.add_combinational(f" .W0_clk(W0_clk),") 1024f24fc9aSDan Tang mem.add_combinational(f" .W0_addr(W0_addr[{new_width-1}:{ways_bits}]),") 1034f24fc9aSDan Tang mem.add_combinational(f" .W0_en(W0_en),") 1044f24fc9aSDan Tang mem.add_combinational(f" .W0_data(data_write),") 1054f24fc9aSDan Tang mem.add_combinational(f" .W0_mask({ways}'h1 << write_way_index),") 1064f24fc9aSDan Tang mem.add_combinational(f" .R0_clk(R0_clk),") 1074f24fc9aSDan Tang mem.add_combinational(f" .R0_addr(R0_addr[{new_width-1}:{ways_bits}]),") 1084f24fc9aSDan Tang mem.add_combinational(f" .R0_en(R0_en),") 1094f24fc9aSDan Tang mem.add_combinational(f" .R0_data(data_read)") 1104f24fc9aSDan Tang mem.add_combinational(f");") 1114f24fc9aSDan Tang mem.add_combinational(f"assign R0_data = ") 1124f24fc9aSDan 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)] 1134f24fc9aSDan Tang mem.add_combinational(":\n ".join(sels) + ";") 1144f24fc9aSDan Tang 1154f24fc9aSDan Tang 1164f24fc9aSDan Tangclass Spliter(object): 1174f24fc9aSDan Tang def __init__(self, before, after): 1184f24fc9aSDan Tang # print(before, after) 1194f24fc9aSDan Tang self.conf = before 1204f24fc9aSDan Tang self.new_conf = after 1214f24fc9aSDan Tang assert(self.conf[-1] == ['mrw']) 1224f24fc9aSDan Tang assert(self.new_conf[-1] == ['rw']) 1234f24fc9aSDan Tang 1244f24fc9aSDan Tang def generate(self, mem): 1254f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 1264f24fc9aSDan Tang (new_name, new_width, new_depth, new_mask_gran, new_mask_seg, _) = self.new_conf 1274f24fc9aSDan Tang assert(depth == new_depth) 1284f24fc9aSDan Tang ways = width // new_width 1294f24fc9aSDan Tang for i in range(ways): 1304f24fc9aSDan Tang data_slice = f"[{new_width*(i+1)-1}:{new_width*i}]" 1314f24fc9aSDan Tang mem.add_combinational(f"{new_name} array_{i} (") 1324f24fc9aSDan Tang mem.add_combinational(f" .RW0_clk(RW0_clk),") 1334f24fc9aSDan Tang mem.add_combinational(f" .RW0_addr(RW0_addr),") 1344f24fc9aSDan Tang mem.add_combinational(f" .RW0_en(RW0_en),") 1354f24fc9aSDan Tang mem.add_combinational(f" .RW0_wmode(RW0_wmode && RW0_wmask[{i}]),") 1364f24fc9aSDan Tang mem.add_combinational(f" .RW0_wdata(RW0_wdata{data_slice}),") 1374f24fc9aSDan Tang mem.add_combinational(f" .RW0_rdata(RW0_rdata{data_slice})") 1384f24fc9aSDan Tang mem.add_combinational(f");") 1394f24fc9aSDan Tang 1404f24fc9aSDan Tangclass SRAM(object): 1414f24fc9aSDan Tang def __init__(self, line): 1424f24fc9aSDan Tang self.parse_line(line) 1434f24fc9aSDan Tang self.prepare_module() 1444f24fc9aSDan Tang 1454f24fc9aSDan Tang def parse_line(self, line): 146885733f1SZihao Yu name = '' 147885733f1SZihao Yu width = 0 148885733f1SZihao Yu depth = 0 149885733f1SZihao Yu ports = '' 150885733f1SZihao Yu mask_gran = 0 151885733f1SZihao Yu tokens = line.split() 152885733f1SZihao Yu i = 0 153885733f1SZihao Yu for i in range(0, len(tokens), 2): 154885733f1SZihao Yu s = tokens[i] 155885733f1SZihao Yu if s == 'name': 156885733f1SZihao Yu name = tokens[i+1] 157885733f1SZihao Yu elif s == 'width': 158885733f1SZihao Yu width = int(tokens[i+1]) 159885733f1SZihao Yu mask_gran = width # default setting 160885733f1SZihao Yu elif s == 'depth': 161885733f1SZihao Yu depth = int(tokens[i+1]) 162885733f1SZihao Yu elif s == 'ports': 163885733f1SZihao Yu ports = tokens[i+1].split(',') 164885733f1SZihao Yu elif s == 'mask_gran': 165885733f1SZihao Yu mask_gran = int(tokens[i+1]) 166885733f1SZihao Yu else: 1674f24fc9aSDan Tang sys.exit('%s: unknown argument %s' % (sys.argv[0], i)) 1684f24fc9aSDan Tang self.conf = (name, width, depth, mask_gran, width//mask_gran, ports) 1694f24fc9aSDan Tang # return (name, width, depth, mask_gran, width//mask_gran, ports) 170885733f1SZihao Yu 1714f24fc9aSDan Tang def prepare_module(self): 1724f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 173885733f1SZihao Yu addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 1744f24fc9aSDan Tang 1754f24fc9aSDan Tang mem = VerilogModuleGenerator(name) 176885733f1SZihao Yu readports = [] 177885733f1SZihao Yu writeports = [] 178885733f1SZihao Yu latchports = [] 179885733f1SZihao Yu rwports = [] 180885733f1SZihao Yu maskedports = {} 1814f24fc9aSDan Tang 1824f24fc9aSDan Tang for pid, ptype in enumerate(ports): 183885733f1SZihao Yu if ptype[0:1] == 'm': 184885733f1SZihao Yu ptype = ptype[1:] 185885733f1SZihao Yu maskedports[pid] = pid 186885733f1SZihao Yu 187885733f1SZihao Yu if ptype == 'read': 188885733f1SZihao Yu prefix = 'R%d_' % len(readports) 1894f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 1904f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 1914f24fc9aSDan Tang mem.add_input(1, prefix + "en") 1924f24fc9aSDan Tang mem.add_output(width, prefix + "data") 193885733f1SZihao Yu readports.append(pid) 194885733f1SZihao Yu elif ptype == 'write': 195885733f1SZihao Yu prefix = 'W%d_' % len(writeports) 1964f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 1974f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 1984f24fc9aSDan Tang mem.add_input(1, prefix + "en") 1994f24fc9aSDan Tang mem.add_input(width, prefix + "data") 200885733f1SZihao Yu if pid in maskedports: 2014f24fc9aSDan Tang mem.add_input(mask_seg, prefix + "mask") 202885733f1SZihao Yu if not use_latches or pid in maskedports: 203885733f1SZihao Yu writeports.append(pid) 204885733f1SZihao Yu else: 205885733f1SZihao Yu latchports.append(pid) 206885733f1SZihao Yu elif ptype == 'rw': 207885733f1SZihao Yu prefix = 'RW%d_' % len(rwports) 2084f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 2094f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 2104f24fc9aSDan Tang mem.add_input(1, prefix + "en") 2114f24fc9aSDan Tang mem.add_input(1, prefix + "wmode") 212885733f1SZihao Yu if pid in maskedports: 2134f24fc9aSDan Tang mem.add_input(mask_seg, prefix + "wmask") 2144f24fc9aSDan Tang mem.add_input(width, prefix + "wdata") 2154f24fc9aSDan Tang mem.add_output(width, prefix + "rdata") 216885733f1SZihao Yu rwports.append(pid) 217885733f1SZihao Yu else: 218885733f1SZihao Yu sys.exit('%s: unknown port type %s' % (sys.argv[0], ptype)) 2194f24fc9aSDan Tang self.mem = mem 2204f24fc9aSDan Tang self.ports_conf = (readports, writeports, latchports, rwports, maskedports) 2214f24fc9aSDan Tang 2224f24fc9aSDan Tang def generate(self, blackbox): 2234f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 2244f24fc9aSDan Tang addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 2254f24fc9aSDan Tang mem, (readports, writeports, latchports, rwports, maskedports) = self.mem, self.ports_conf 226885733f1SZihao Yu 227885733f1SZihao Yu nr = len(readports) 228885733f1SZihao Yu nw = len(writeports) 229885733f1SZihao Yu nrw = len(rwports) 230885733f1SZihao Yu 231885733f1SZihao Yu def emit_read(idx, rw): 232885733f1SZihao Yu prefix = ('RW%d_' if rw else 'R%d_') % idx 233885733f1SZihao Yu data = ('%srdata' if rw else '%sdata') % prefix 234885733f1SZihao Yu en = ('%sen && !%swmode' % (prefix, prefix)) if rw else ('%sen' % prefix) 2354f24fc9aSDan Tang mem.add_decl_reg(1, f"reg_{prefix}ren") 2364f24fc9aSDan Tang mem.add_decl_reg(addr_width, f"reg_{prefix}addr") 2374f24fc9aSDan Tang mem.add_sequential(f"always @(posedge {prefix}clk)") 2384f24fc9aSDan Tang mem.add_sequential(f" reg_{prefix}ren <= {en};") 2394f24fc9aSDan Tang mem.add_sequential(f"always @(posedge {prefix}clk)") 2404f24fc9aSDan Tang mem.add_sequential(f" if ({en}) reg_{prefix}addr <= {prefix}addr;") 2414f24fc9aSDan Tang mem.add_combinational("`ifdef RANDOMIZE_GARBAGE_ASSIGN") 2424f24fc9aSDan Tang mem.add_combinational(f"reg [{((width-1)//32+1)*32-1}:0] {prefix}random;") 2434f24fc9aSDan Tang mem.add_combinational(f"`ifdef RANDOMIZE_MEM_INIT") 2444f24fc9aSDan Tang mem.add_combinational(f" initial begin") 2454f24fc9aSDan Tang mem.add_combinational(f" #`RANDOMIZE_DELAY begin end") 2464f24fc9aSDan Tang mem.add_combinational(' %srandom = {%s};' % (prefix, ', '.join(['$random'] * ((width-1)//32+1)))) 2474f24fc9aSDan Tang mem.add_combinational(' reg_%sren = %srandom[0];' % (prefix, prefix)) 2484f24fc9aSDan Tang mem.add_combinational(' end') 2494f24fc9aSDan Tang mem.add_combinational('`endif') 2504f24fc9aSDan Tang mem.add_combinational('always @(posedge %sclk) %srandom <= {%s};' % (prefix, prefix, ', '.join(['$random'] * ((width-1)//32+1)))) 2514f24fc9aSDan Tang mem.add_combinational('assign %s = reg_%sren ? ram[reg_%saddr] : %srandom[%d:0];' % (data, prefix, prefix, prefix, width-1)) 2524f24fc9aSDan Tang mem.add_combinational('`else') 2534f24fc9aSDan Tang mem.add_combinational('assign %s = ram[reg_%saddr];' % (data, prefix)) 2544f24fc9aSDan Tang mem.add_combinational('`endif') 255885733f1SZihao Yu 256885733f1SZihao Yu for idx in range(nr): 257885733f1SZihao Yu emit_read(idx, False) 258885733f1SZihao Yu 259885733f1SZihao Yu for idx in range(nrw): 260885733f1SZihao Yu emit_read(idx, True) 261885733f1SZihao Yu 262885733f1SZihao Yu for idx in range(len(latchports)): 263885733f1SZihao Yu prefix = 'W%d_' % idx 2644f24fc9aSDan Tang mem.add_decl_reg(addr_width, f"latch_{prefix}addr") 2654f24fc9aSDan Tang mem.add_decl_reg(width, f"latch_{prefix}data") 2664f24fc9aSDan Tang mem.add_decl_reg(1, f"latch_{prefix}en") 2674f24fc9aSDan Tang mem.add_combinational('always @(*) begin') 2684f24fc9aSDan Tang mem.add_combinational(' if (!%sclk && %sen) latch_%saddr <= %saddr;' % (prefix, prefix, prefix, prefix)) 2694f24fc9aSDan Tang mem.add_combinational(' if (!%sclk && %sen) latch_%sdata <= %sdata;' % (prefix, prefix, prefix, prefix)) 2704f24fc9aSDan Tang mem.add_combinational(' if (!%sclk) latch_%sen <= %sen;' % (prefix, prefix, prefix)) 2714f24fc9aSDan Tang mem.add_combinational('end') 2724f24fc9aSDan Tang mem.add_combinational('always @(*)') 2734f24fc9aSDan Tang mem.add_combinational(' if (%sclk && latch_%sen)' % (prefix, prefix)) 2744f24fc9aSDan Tang mem.add_combinational(' ram[latch_%saddr] <= latch_%sdata;' % (prefix, prefix)) 275885733f1SZihao Yu 27651e45dbbSTang Haojin mem.add_decl_ram(width, "ram", depth) 2774f24fc9aSDan Tang mem.add_decl_line('`ifdef RANDOMIZE_MEM_INIT') 2784f24fc9aSDan Tang mem.add_decl_line(' integer initvar;') 2794f24fc9aSDan Tang mem.add_decl_line(' initial begin') 2804f24fc9aSDan Tang mem.add_decl_line(' #`RANDOMIZE_DELAY begin end') 2814f24fc9aSDan Tang mem.add_decl_line(' for (initvar = 0; initvar < %d; initvar = initvar+1)' % depth) 2824f24fc9aSDan Tang mem.add_decl_line(' ram[initvar] = {%d {$random}};' % ((width-1)//32+1)) 283885733f1SZihao Yu for idx in range(nr): 284885733f1SZihao Yu prefix = 'R%d_' % idx 2854f24fc9aSDan Tang mem.add_decl_line(' reg_%saddr = {%d {$random}};' % (prefix, ((addr_width-1)//32+1))) 286885733f1SZihao Yu for idx in range(nrw): 287885733f1SZihao Yu prefix = 'RW%d_' % idx 2884f24fc9aSDan Tang mem.add_decl_line(' reg_%saddr = {%d {$random}};' % (prefix, ((addr_width-1)//32+1))) 2894f24fc9aSDan Tang mem.add_decl_line(' end') 2904f24fc9aSDan Tang mem.add_decl_line('`endif') 291885733f1SZihao Yu 2924f24fc9aSDan Tang mem.add_decl_line("integer i;") 293885733f1SZihao Yu for idx in range(nw): 294885733f1SZihao Yu prefix = 'W%d_' % idx 295885733f1SZihao Yu pid = writeports[idx] 2964f24fc9aSDan Tang mem.add_sequential('always @(posedge %sclk)' % prefix) 2974f24fc9aSDan Tang mem.add_sequential(" if (%sen) begin" % prefix) 298885733f1SZihao Yu for i in range(mask_seg): 299885733f1SZihao Yu mask = ('if (%smask[%d]) ' % (prefix, i)) if pid in maskedports else '' 300885733f1SZihao Yu ram_range = '%d:%d' % ((i+1)*mask_gran-1, i*mask_gran) 3014f24fc9aSDan Tang mem.add_sequential(" %sram[%saddr][%s] <= %sdata[%s];" % (mask, prefix, ram_range, prefix, ram_range)) 3024f24fc9aSDan Tang mem.add_sequential(" end") 303885733f1SZihao Yu for idx in range(nrw): 304885733f1SZihao Yu pid = rwports[idx] 305885733f1SZihao Yu prefix = 'RW%d_' % idx 3064f24fc9aSDan Tang mem.add_sequential('always @(posedge %sclk)' % prefix) 3074f24fc9aSDan Tang mem.add_sequential(" if (%sen && %swmode) begin" % (prefix, prefix)) 308885733f1SZihao Yu if mask_seg > 0: 309ac271a23SEaston Man if mask_gran == 1: # If 1 bit mask, use & instead 310ac271a23SEaston Man if pid in maskedports: 311*7ee24868SEaston Man mem.add_sequential(" ram[%saddr] <= (%swmask & %swdata) | (~%swmask & ram[%saddr]);" %(prefix, prefix, prefix, prefix, prefix)) 312ac271a23SEaston Man else: 313ac271a23SEaston Man mem.add_sequential(" ram[%saddr] <= %swdata;" %(prefix, prefix)) 314ac271a23SEaston Man else: 3154f24fc9aSDan Tang mem.add_sequential(" for (i=0;i<%d;i=i+1) begin" % mask_seg) 316885733f1SZihao Yu if pid in maskedports: 3174f24fc9aSDan Tang mem.add_sequential(" if (%swmask[i]) begin" % prefix) 3184f24fc9aSDan Tang mem.add_sequential(" ram[%saddr][i*%d +: %d] <= %swdata[i*%d +: %d];" %(prefix, mask_gran, mask_gran, prefix, mask_gran, mask_gran)) 3194f24fc9aSDan Tang mem.add_sequential(" end") 320885733f1SZihao Yu else: 3214f24fc9aSDan Tang mem.add_sequential(" ram[%saddr][i*%d +: %d] <= %swdata[i*%d +: %d];" %(prefix, mask_gran, mask_gran, prefix, mask_gran, mask_gran)) 3224f24fc9aSDan Tang mem.add_sequential(" end") 3234f24fc9aSDan Tang mem.add_sequential(" end") 3244f24fc9aSDan Tang return mem.generate(blackbox) 325885733f1SZihao Yu 3264f24fc9aSDan Tang 3274f24fc9aSDan Tangclass SRAM_TSMC28(SRAM): 3284f24fc9aSDan Tang def __init__(self, line): 3294f24fc9aSDan Tang super().__init__(line) 3304f24fc9aSDan Tang self.sub_srams = [] 3314f24fc9aSDan Tang if self.__check_subsrams(): 3324f24fc9aSDan Tang print(line.strip()) 3334f24fc9aSDan Tang 3344f24fc9aSDan Tang def __check_subsrams(self): 3354f24fc9aSDan Tang need_split = self.__split() 3364f24fc9aSDan Tang need_reshape = self.__reshape() 3374f24fc9aSDan Tang assert(not (need_split and need_reshape)) 3384f24fc9aSDan Tang return not need_split and not need_reshape 3394f24fc9aSDan Tang 3404f24fc9aSDan Tang def __split(self): 3414f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 342eae78b10SYinan Xu '''if ports == ["mrw"] and mask_gran >= 32: 3434f24fc9aSDan Tang new_conf = (name + "_sub", str(depth), str(mask_gran), "rw") 3444f24fc9aSDan Tang line_field = ("name", "depth", "width", "ports") 3454f24fc9aSDan Tang new_line = " ".join(map(lambda x: " ".join(x), zip(line_field, new_conf))) 3464f24fc9aSDan Tang new_sram = SRAM_TSMC28(new_line) 3474f24fc9aSDan Tang self.sub_srams.append(new_sram) 3484f24fc9aSDan Tang reshaper = Spliter(self.conf, new_sram.conf) 3494f24fc9aSDan Tang reshaper.generate(self.mem) 350eae78b10SYinan Xu return True''' 3514f24fc9aSDan Tang return False 3524f24fc9aSDan Tang 3534f24fc9aSDan Tang def __reshape(self): 3544f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 3554f24fc9aSDan Tang if width == 2 and depth == 256: 3564f24fc9aSDan Tang new_conf = (name + "_sub", "64", "8", "mwrite,read", "2") 3574f24fc9aSDan Tang line_field = ("name", "depth", "width", "ports", "mask_gran") 3584f24fc9aSDan Tang new_line = " ".join(map(lambda x: " ".join(x), zip(line_field, new_conf))) 3594f24fc9aSDan Tang new_sram = SRAM_TSMC28(new_line) 3604f24fc9aSDan Tang self.sub_srams.append(new_sram) 3614f24fc9aSDan Tang reshaper = Reshaper(self.conf, new_sram.conf) 3624f24fc9aSDan Tang reshaper.generate(self.mem) 3634f24fc9aSDan Tang return True 3644f24fc9aSDan Tang return False 3654f24fc9aSDan Tang 3664f24fc9aSDan Tang def __get_tsmc_lib(self): 3674f24fc9aSDan Tang mem, (readports, writeports, latchports, rwports, maskedports) = self.mem, self.ports_conf 3684f24fc9aSDan Tang blackbox = "// tsmc lib here\n" 3694f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 3704f24fc9aSDan Tang nports = (len(readports), len(writeports), len(rwports)) 3714f24fc9aSDan Tang addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 3724f24fc9aSDan Tang masked = len(maskedports) > 0 3734f24fc9aSDan Tang # from tsmc28_sram import gen_tsmc_ram_1pw, gen_tsmc_ram_1pnw, gen_tsmc_ram_2pw, gen_tsmc_ram_2pnw 3744f24fc9aSDan Tang # if nports == (1, 1, 0): 3754f24fc9aSDan Tang # if masked: 3764f24fc9aSDan Tang # blackbox = gen_tsmc_ram_2pw("TS6N28HPCPLVTA64X8M2F", width, mask_gran) 3774f24fc9aSDan Tang # else: 3784f24fc9aSDan Tang # blackbox = gen_tsmc_ram_2pnw("TS6N28HPCPLVTA64X14M2F") 3794f24fc9aSDan Tang # elif nports == (0, 0, 1): 3804f24fc9aSDan Tang # if masked: 3814f24fc9aSDan Tang # blackbox = gen_tsmc_ram_1pw('TS1N28HPCPLVTB8192X64M8SW', width, mask_gran, addr_width) 3824f24fc9aSDan Tang # else: 3834f24fc9aSDan Tang # blackbox = gen_tsmc_ram_1pnw('TS5N28HPCPLVTA64X144M2F', width, addr_width) 3844f24fc9aSDan Tang # else: 3854f24fc9aSDan Tang # blackbox = "// unknown tsmc lib type\n" 3864f24fc9aSDan Tang return mem.generate(blackbox) 3874f24fc9aSDan Tang 3884f24fc9aSDan Tang def generate(self, blackbox, itself_only=False): 3894f24fc9aSDan Tang if itself_only: 3904f24fc9aSDan Tang # generate splits or reshapes 3914f24fc9aSDan Tang if self.sub_srams: 3924f24fc9aSDan Tang return self.mem.generate("") 3934f24fc9aSDan Tang # use empty blackbox 3944f24fc9aSDan Tang elif blackbox: 3954f24fc9aSDan Tang return super().generate(" ") 3964f24fc9aSDan Tang # insert tsmc libs 3974f24fc9aSDan Tang else: 3984f24fc9aSDan Tang return self.__get_tsmc_lib() 3994f24fc9aSDan Tang else: 4004f24fc9aSDan Tang s = self.generate(blackbox, True) 4014f24fc9aSDan Tang for sram in self.sub_srams: 4024f24fc9aSDan Tang s += sram.generate(blackbox) 403885733f1SZihao Yu return s 404885733f1SZihao Yu 4054f24fc9aSDan Tang 406885733f1SZihao Yudef main(args): 407885733f1SZihao Yu f = open(args.output_file, "w") if (args.output_file) else None 408885733f1SZihao Yu conf_file = args.conf 409885733f1SZihao Yu for line in open(conf_file): 4104f24fc9aSDan Tang sram = SRAM(line) 4114f24fc9aSDan Tang if args.tsmc28: 4124f24fc9aSDan Tang sram = SRAM_TSMC28(line) 413885733f1SZihao Yu else: 4144f24fc9aSDan Tang sram = SRAM(line) 4154f24fc9aSDan Tang if f is not None: 4164f24fc9aSDan Tang f.write(sram.generate(args.blackbox)) 4174f24fc9aSDan Tang else: 4184f24fc9aSDan Tang print(sram.generate(args.blackbox)) 4194f24fc9aSDan Tang 420885733f1SZihao Yu 421885733f1SZihao Yuif __name__ == '__main__': 422885733f1SZihao Yu import argparse 423885733f1SZihao Yu parser = argparse.ArgumentParser(description='Memory generator for Rocket Chip') 424885733f1SZihao Yu parser.add_argument('conf', metavar='.conf file') 4254f24fc9aSDan Tang parser.add_argument('--tsmc28', action='store_true', help='use tsmc28 sram to generate module body') 426885733f1SZihao Yu parser.add_argument('--blackbox', '-b', action='store_true', help='set to disable output of module body') 427885733f1SZihao Yu #parser.add_argument('--use_latches', '-l', action='store_true', help='set to enable use of latches') 428885733f1SZihao Yu parser.add_argument('--output_file', '-o', help='name of output file, default is stdout') 429885733f1SZihao Yu args = parser.parse_args() 430885733f1SZihao Yu #use_latches = args.use_latches 431885733f1SZihao Yu main(args) 432