1*4f24fc9aSDan 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 11*4f24fc9aSDan Tangclass VerilogModuleGenerator(object): 12*4f24fc9aSDan Tang def __init__(self, name): 13*4f24fc9aSDan Tang self.name = name 14*4f24fc9aSDan Tang self.port_spec = [] 15*4f24fc9aSDan Tang self.decl = [] 16*4f24fc9aSDan Tang self.combinational = [] 17*4f24fc9aSDan Tang self.sequential = [] 18*4f24fc9aSDan Tang 19*4f24fc9aSDan Tang def __format_width(self, width): 20*4f24fc9aSDan Tang return "[{}:0] ".format(width-1) if width > 1 else "" 21*4f24fc9aSDan Tang 22*4f24fc9aSDan Tang def __format_depth(self, depth): 23*4f24fc9aSDan Tang return " [{}:0]".format(depth-1) if depth > 1 else "" 24*4f24fc9aSDan Tang 25*4f24fc9aSDan Tang def add_io(self, io_type, width, name): 26*4f24fc9aSDan Tang width_str = self.__format_width(width) 27*4f24fc9aSDan Tang # print(io_type, width_str, name) 28*4f24fc9aSDan Tang self.port_spec.append(f'{io_type} {width_str}{name}') 29*4f24fc9aSDan Tang 30*4f24fc9aSDan Tang def add_input(self, width, name): 31*4f24fc9aSDan Tang self.add_io("input", width, name) 32*4f24fc9aSDan Tang 33*4f24fc9aSDan Tang def add_output(self, width, name): 34*4f24fc9aSDan Tang self.add_io("output", width, name) 35*4f24fc9aSDan Tang 36*4f24fc9aSDan Tang def add_decl(self, decl_type, width, name, depth=1): 37*4f24fc9aSDan Tang width_str = self.__format_width(width) 38*4f24fc9aSDan Tang depth_str = self.__format_depth(depth) 39*4f24fc9aSDan Tang self.decl.append(f"{decl_type} {width_str}{name}{depth_str};") 40*4f24fc9aSDan Tang 41*4f24fc9aSDan Tang def add_decl_reg(self, width, name, depth=1): 42*4f24fc9aSDan Tang self.add_decl("reg", width, name, depth) 43*4f24fc9aSDan Tang 44*4f24fc9aSDan Tang def add_decl_wire(self, width, name, depth=1): 45*4f24fc9aSDan Tang self.add_decl("wire", width, name, depth) 46*4f24fc9aSDan Tang 47*4f24fc9aSDan Tang def add_decl_line(self, line): 48*4f24fc9aSDan Tang self.decl.append(line) 49*4f24fc9aSDan Tang 50*4f24fc9aSDan Tang def add_sequential(self, line): 51*4f24fc9aSDan Tang self.sequential.append(line) 52*4f24fc9aSDan Tang 53*4f24fc9aSDan Tang def add_combinational(self, line): 54*4f24fc9aSDan Tang self.combinational.append(line) 55*4f24fc9aSDan Tang 56*4f24fc9aSDan Tang def generate(self, blackbox): 57*4f24fc9aSDan Tang body = "\ 58*4f24fc9aSDan Tang %s\n\ 59*4f24fc9aSDan Tang %s\n\ 60*4f24fc9aSDan Tang %s\n" % ('\n '.join(self.decl), '\n '.join(self.sequential), '\n '.join(self.combinational)) 61*4f24fc9aSDan Tang 62*4f24fc9aSDan Tang s = "\nmodule %s(\n\ 63*4f24fc9aSDan Tang %s\n\ 64*4f24fc9aSDan Tang);\n\ 65*4f24fc9aSDan Tang\n\ 66*4f24fc9aSDan Tang%s\ 67*4f24fc9aSDan Tang\n\ 68*4f24fc9aSDan Tangendmodule" % (self.name, ',\n '.join(self.port_spec), body if not blackbox else blackbox) 69*4f24fc9aSDan Tang return s 70*4f24fc9aSDan Tang 71*4f24fc9aSDan Tang 72*4f24fc9aSDan Tangclass Reshaper(object): 73*4f24fc9aSDan Tang def __init__(self, before, after): 74*4f24fc9aSDan Tang # print(before, after) 75*4f24fc9aSDan Tang self.conf = before 76*4f24fc9aSDan Tang self.new_conf = after 77*4f24fc9aSDan Tang assert(self.conf[-1] == ['write', 'read']) 78*4f24fc9aSDan Tang assert(self.new_conf[-1] == ['mwrite', 'read']) 79*4f24fc9aSDan Tang 80*4f24fc9aSDan Tang def generate(self, mem): 81*4f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 82*4f24fc9aSDan Tang (new_name, new_width, new_depth, new_mask_gran, new_mask_seg, _) = self.new_conf 83*4f24fc9aSDan Tang addr_bits = math.log2(depth) 84*4f24fc9aSDan Tang ways = new_width // width 85*4f24fc9aSDan Tang ways_bits = int(math.log2(ways)) 86*4f24fc9aSDan Tang mem.add_decl_wire(new_width, "data_read") 87*4f24fc9aSDan Tang mem.add_decl_wire(new_width, "data_write") 88*4f24fc9aSDan Tang mem.add_combinational(f"assign data_write = ") 89*4f24fc9aSDan 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)] 90*4f24fc9aSDan Tang mem.add_combinational(":\n ".join(sels) + ";") 91*4f24fc9aSDan Tang mem.add_decl_wire(ways_bits, "read_way_index") 92*4f24fc9aSDan Tang mem.add_combinational(f"assign read_way_index = R0_addr[{ways_bits-1}:0];") 93*4f24fc9aSDan Tang mem.add_decl_wire(ways_bits, "write_way_index") 94*4f24fc9aSDan Tang mem.add_combinational(f"assign write_way_index = W0_addr[{ways_bits-1}:0];") 95*4f24fc9aSDan Tang mem.add_combinational(f"{new_name} array (") 96*4f24fc9aSDan Tang mem.add_combinational(f" .W0_clk(W0_clk),") 97*4f24fc9aSDan Tang mem.add_combinational(f" .W0_addr(W0_addr[{new_width-1}:{ways_bits}]),") 98*4f24fc9aSDan Tang mem.add_combinational(f" .W0_en(W0_en),") 99*4f24fc9aSDan Tang mem.add_combinational(f" .W0_data(data_write),") 100*4f24fc9aSDan Tang mem.add_combinational(f" .W0_mask({ways}'h1 << write_way_index),") 101*4f24fc9aSDan Tang mem.add_combinational(f" .R0_clk(R0_clk),") 102*4f24fc9aSDan Tang mem.add_combinational(f" .R0_addr(R0_addr[{new_width-1}:{ways_bits}]),") 103*4f24fc9aSDan Tang mem.add_combinational(f" .R0_en(R0_en),") 104*4f24fc9aSDan Tang mem.add_combinational(f" .R0_data(data_read)") 105*4f24fc9aSDan Tang mem.add_combinational(f");") 106*4f24fc9aSDan Tang mem.add_combinational(f"assign R0_data = ") 107*4f24fc9aSDan 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)] 108*4f24fc9aSDan Tang mem.add_combinational(":\n ".join(sels) + ";") 109*4f24fc9aSDan Tang 110*4f24fc9aSDan Tang 111*4f24fc9aSDan Tangclass Spliter(object): 112*4f24fc9aSDan Tang def __init__(self, before, after): 113*4f24fc9aSDan Tang # print(before, after) 114*4f24fc9aSDan Tang self.conf = before 115*4f24fc9aSDan Tang self.new_conf = after 116*4f24fc9aSDan Tang assert(self.conf[-1] == ['mrw']) 117*4f24fc9aSDan Tang assert(self.new_conf[-1] == ['rw']) 118*4f24fc9aSDan Tang 119*4f24fc9aSDan Tang def generate(self, mem): 120*4f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 121*4f24fc9aSDan Tang (new_name, new_width, new_depth, new_mask_gran, new_mask_seg, _) = self.new_conf 122*4f24fc9aSDan Tang assert(depth == new_depth) 123*4f24fc9aSDan Tang ways = width // new_width 124*4f24fc9aSDan Tang for i in range(ways): 125*4f24fc9aSDan Tang data_slice = f"[{new_width*(i+1)-1}:{new_width*i}]" 126*4f24fc9aSDan Tang mem.add_combinational(f"{new_name} array_{i} (") 127*4f24fc9aSDan Tang mem.add_combinational(f" .RW0_clk(RW0_clk),") 128*4f24fc9aSDan Tang mem.add_combinational(f" .RW0_addr(RW0_addr),") 129*4f24fc9aSDan Tang mem.add_combinational(f" .RW0_en(RW0_en),") 130*4f24fc9aSDan Tang mem.add_combinational(f" .RW0_wmode(RW0_wmode && RW0_wmask[{i}]),") 131*4f24fc9aSDan Tang mem.add_combinational(f" .RW0_wdata(RW0_wdata{data_slice}),") 132*4f24fc9aSDan Tang mem.add_combinational(f" .RW0_rdata(RW0_rdata{data_slice})") 133*4f24fc9aSDan Tang mem.add_combinational(f");") 134*4f24fc9aSDan Tang 135*4f24fc9aSDan Tangclass SRAM(object): 136*4f24fc9aSDan Tang def __init__(self, line): 137*4f24fc9aSDan Tang self.parse_line(line) 138*4f24fc9aSDan Tang self.prepare_module() 139*4f24fc9aSDan Tang 140*4f24fc9aSDan 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: 162*4f24fc9aSDan Tang sys.exit('%s: unknown argument %s' % (sys.argv[0], i)) 163*4f24fc9aSDan Tang self.conf = (name, width, depth, mask_gran, width//mask_gran, ports) 164*4f24fc9aSDan Tang # return (name, width, depth, mask_gran, width//mask_gran, ports) 165885733f1SZihao Yu 166*4f24fc9aSDan Tang def prepare_module(self): 167*4f24fc9aSDan 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) 169*4f24fc9aSDan Tang 170*4f24fc9aSDan Tang mem = VerilogModuleGenerator(name) 171885733f1SZihao Yu readports = [] 172885733f1SZihao Yu writeports = [] 173885733f1SZihao Yu latchports = [] 174885733f1SZihao Yu rwports = [] 175885733f1SZihao Yu maskedports = {} 176*4f24fc9aSDan Tang 177*4f24fc9aSDan 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) 184*4f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 185*4f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 186*4f24fc9aSDan Tang mem.add_input(1, prefix + "en") 187*4f24fc9aSDan Tang mem.add_output(width, prefix + "data") 188885733f1SZihao Yu readports.append(pid) 189885733f1SZihao Yu elif ptype == 'write': 190885733f1SZihao Yu prefix = 'W%d_' % len(writeports) 191*4f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 192*4f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 193*4f24fc9aSDan Tang mem.add_input(1, prefix + "en") 194*4f24fc9aSDan Tang mem.add_input(width, prefix + "data") 195885733f1SZihao Yu if pid in maskedports: 196*4f24fc9aSDan 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) 203*4f24fc9aSDan Tang mem.add_input(1, prefix + "clk") 204*4f24fc9aSDan Tang mem.add_input(addr_width, prefix + "addr") 205*4f24fc9aSDan Tang mem.add_input(1, prefix + "en") 206*4f24fc9aSDan Tang mem.add_input(1, prefix + "wmode") 207885733f1SZihao Yu if pid in maskedports: 208*4f24fc9aSDan Tang mem.add_input(mask_seg, prefix + "wmask") 209*4f24fc9aSDan Tang mem.add_input(width, prefix + "wdata") 210*4f24fc9aSDan 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)) 214*4f24fc9aSDan Tang self.mem = mem 215*4f24fc9aSDan Tang self.ports_conf = (readports, writeports, latchports, rwports, maskedports) 216*4f24fc9aSDan Tang 217*4f24fc9aSDan Tang def generate(self, blackbox): 218*4f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 219*4f24fc9aSDan Tang addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 220*4f24fc9aSDan 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) 230*4f24fc9aSDan Tang mem.add_decl_reg(1, f"reg_{prefix}ren") 231*4f24fc9aSDan Tang mem.add_decl_reg(addr_width, f"reg_{prefix}addr") 232*4f24fc9aSDan Tang mem.add_sequential(f"always @(posedge {prefix}clk)") 233*4f24fc9aSDan Tang mem.add_sequential(f" reg_{prefix}ren <= {en};") 234*4f24fc9aSDan Tang mem.add_sequential(f"always @(posedge {prefix}clk)") 235*4f24fc9aSDan Tang mem.add_sequential(f" if ({en}) reg_{prefix}addr <= {prefix}addr;") 236*4f24fc9aSDan Tang mem.add_combinational("`ifdef RANDOMIZE_GARBAGE_ASSIGN") 237*4f24fc9aSDan Tang mem.add_combinational(f"reg [{((width-1)//32+1)*32-1}:0] {prefix}random;") 238*4f24fc9aSDan Tang mem.add_combinational(f"`ifdef RANDOMIZE_MEM_INIT") 239*4f24fc9aSDan Tang mem.add_combinational(f" initial begin") 240*4f24fc9aSDan Tang mem.add_combinational(f" #`RANDOMIZE_DELAY begin end") 241*4f24fc9aSDan Tang mem.add_combinational(' %srandom = {%s};' % (prefix, ', '.join(['$random'] * ((width-1)//32+1)))) 242*4f24fc9aSDan Tang mem.add_combinational(' reg_%sren = %srandom[0];' % (prefix, prefix)) 243*4f24fc9aSDan Tang mem.add_combinational(' end') 244*4f24fc9aSDan Tang mem.add_combinational('`endif') 245*4f24fc9aSDan Tang mem.add_combinational('always @(posedge %sclk) %srandom <= {%s};' % (prefix, prefix, ', '.join(['$random'] * ((width-1)//32+1)))) 246*4f24fc9aSDan Tang mem.add_combinational('assign %s = reg_%sren ? ram[reg_%saddr] : %srandom[%d:0];' % (data, prefix, prefix, prefix, width-1)) 247*4f24fc9aSDan Tang mem.add_combinational('`else') 248*4f24fc9aSDan Tang mem.add_combinational('assign %s = ram[reg_%saddr];' % (data, prefix)) 249*4f24fc9aSDan 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 259*4f24fc9aSDan Tang mem.add_decl_reg(addr_width, f"latch_{prefix}addr") 260*4f24fc9aSDan Tang mem.add_decl_reg(width, f"latch_{prefix}data") 261*4f24fc9aSDan Tang mem.add_decl_reg(1, f"latch_{prefix}en") 262*4f24fc9aSDan Tang mem.add_combinational('always @(*) begin') 263*4f24fc9aSDan Tang mem.add_combinational(' if (!%sclk && %sen) latch_%saddr <= %saddr;' % (prefix, prefix, prefix, prefix)) 264*4f24fc9aSDan Tang mem.add_combinational(' if (!%sclk && %sen) latch_%sdata <= %sdata;' % (prefix, prefix, prefix, prefix)) 265*4f24fc9aSDan Tang mem.add_combinational(' if (!%sclk) latch_%sen <= %sen;' % (prefix, prefix, prefix)) 266*4f24fc9aSDan Tang mem.add_combinational('end') 267*4f24fc9aSDan Tang mem.add_combinational('always @(*)') 268*4f24fc9aSDan Tang mem.add_combinational(' if (%sclk && latch_%sen)' % (prefix, prefix)) 269*4f24fc9aSDan Tang mem.add_combinational(' ram[latch_%saddr] <= latch_%sdata;' % (prefix, prefix)) 270885733f1SZihao Yu 271*4f24fc9aSDan Tang mem.add_decl_reg(width, "ram", depth) 272*4f24fc9aSDan Tang mem.add_decl_line('`ifdef RANDOMIZE_MEM_INIT') 273*4f24fc9aSDan Tang mem.add_decl_line(' integer initvar;') 274*4f24fc9aSDan Tang mem.add_decl_line(' initial begin') 275*4f24fc9aSDan Tang mem.add_decl_line(' #`RANDOMIZE_DELAY begin end') 276*4f24fc9aSDan Tang mem.add_decl_line(' for (initvar = 0; initvar < %d; initvar = initvar+1)' % depth) 277*4f24fc9aSDan 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 280*4f24fc9aSDan 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 283*4f24fc9aSDan Tang mem.add_decl_line(' reg_%saddr = {%d {$random}};' % (prefix, ((addr_width-1)//32+1))) 284*4f24fc9aSDan Tang mem.add_decl_line(' end') 285*4f24fc9aSDan Tang mem.add_decl_line('`endif') 286885733f1SZihao Yu 287*4f24fc9aSDan 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] 291*4f24fc9aSDan Tang mem.add_sequential('always @(posedge %sclk)' % prefix) 292*4f24fc9aSDan 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) 296*4f24fc9aSDan Tang mem.add_sequential(" %sram[%saddr][%s] <= %sdata[%s];" % (mask, prefix, ram_range, prefix, ram_range)) 297*4f24fc9aSDan Tang mem.add_sequential(" end") 298885733f1SZihao Yu for idx in range(nrw): 299885733f1SZihao Yu pid = rwports[idx] 300885733f1SZihao Yu prefix = 'RW%d_' % idx 301*4f24fc9aSDan Tang mem.add_sequential('always @(posedge %sclk)' % prefix) 302*4f24fc9aSDan Tang mem.add_sequential(" if (%sen && %swmode) begin" % (prefix, prefix)) 303885733f1SZihao Yu if mask_seg > 0: 304*4f24fc9aSDan Tang mem.add_sequential(" for(i=0;i<%d;i=i+1) begin" % mask_seg) 305885733f1SZihao Yu if pid in maskedports: 306*4f24fc9aSDan Tang mem.add_sequential(" if(%swmask[i]) begin" % prefix) 307*4f24fc9aSDan Tang mem.add_sequential(" ram[%saddr][i*%d +: %d] <= %swdata[i*%d +: %d];" %(prefix, mask_gran, mask_gran, prefix, mask_gran, mask_gran)) 308*4f24fc9aSDan Tang mem.add_sequential(" end") 309885733f1SZihao Yu else: 310*4f24fc9aSDan Tang mem.add_sequential(" ram[%saddr][i*%d +: %d] <= %swdata[i*%d +: %d];" %(prefix, mask_gran, mask_gran, prefix, mask_gran, mask_gran)) 311*4f24fc9aSDan Tang mem.add_sequential(" end") 312*4f24fc9aSDan Tang mem.add_sequential(" end") 313*4f24fc9aSDan Tang return mem.generate(blackbox) 314885733f1SZihao Yu 315*4f24fc9aSDan Tang 316*4f24fc9aSDan Tangclass SRAM_TSMC28(SRAM): 317*4f24fc9aSDan Tang def __init__(self, line): 318*4f24fc9aSDan Tang super().__init__(line) 319*4f24fc9aSDan Tang self.sub_srams = [] 320*4f24fc9aSDan Tang if self.__check_subsrams(): 321*4f24fc9aSDan Tang print(line.strip()) 322*4f24fc9aSDan Tang 323*4f24fc9aSDan Tang def __check_subsrams(self): 324*4f24fc9aSDan Tang need_split = self.__split() 325*4f24fc9aSDan Tang need_reshape = self.__reshape() 326*4f24fc9aSDan Tang assert(not (need_split and need_reshape)) 327*4f24fc9aSDan Tang return not need_split and not need_reshape 328*4f24fc9aSDan Tang 329*4f24fc9aSDan Tang def __split(self): 330*4f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 331*4f24fc9aSDan Tang if ports == ["mrw"]: 332*4f24fc9aSDan Tang new_conf = (name + "_sub", str(depth), str(mask_gran), "rw") 333*4f24fc9aSDan Tang line_field = ("name", "depth", "width", "ports") 334*4f24fc9aSDan Tang new_line = " ".join(map(lambda x: " ".join(x), zip(line_field, new_conf))) 335*4f24fc9aSDan Tang new_sram = SRAM_TSMC28(new_line) 336*4f24fc9aSDan Tang self.sub_srams.append(new_sram) 337*4f24fc9aSDan Tang reshaper = Spliter(self.conf, new_sram.conf) 338*4f24fc9aSDan Tang reshaper.generate(self.mem) 339*4f24fc9aSDan Tang return True 340*4f24fc9aSDan Tang return False 341*4f24fc9aSDan Tang 342*4f24fc9aSDan Tang def __reshape(self): 343*4f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, ports) = self.conf 344*4f24fc9aSDan Tang if width == 2 and depth == 256: 345*4f24fc9aSDan Tang new_conf = (name + "_sub", "64", "8", "mwrite,read", "2") 346*4f24fc9aSDan Tang line_field = ("name", "depth", "width", "ports", "mask_gran") 347*4f24fc9aSDan Tang new_line = " ".join(map(lambda x: " ".join(x), zip(line_field, new_conf))) 348*4f24fc9aSDan Tang new_sram = SRAM_TSMC28(new_line) 349*4f24fc9aSDan Tang self.sub_srams.append(new_sram) 350*4f24fc9aSDan Tang reshaper = Reshaper(self.conf, new_sram.conf) 351*4f24fc9aSDan Tang reshaper.generate(self.mem) 352*4f24fc9aSDan Tang return True 353*4f24fc9aSDan Tang return False 354*4f24fc9aSDan Tang 355*4f24fc9aSDan Tang def __get_tsmc_lib(self): 356*4f24fc9aSDan Tang mem, (readports, writeports, latchports, rwports, maskedports) = self.mem, self.ports_conf 357*4f24fc9aSDan Tang blackbox = "// tsmc lib here\n" 358*4f24fc9aSDan Tang (name, width, depth, mask_gran, mask_seg, _) = self.conf 359*4f24fc9aSDan Tang nports = (len(readports), len(writeports), len(rwports)) 360*4f24fc9aSDan Tang addr_width = max(math.ceil(math.log(depth)/math.log(2)),1) 361*4f24fc9aSDan Tang masked = len(maskedports) > 0 362*4f24fc9aSDan Tang # from tsmc28_sram import gen_tsmc_ram_1pw, gen_tsmc_ram_1pnw, gen_tsmc_ram_2pw, gen_tsmc_ram_2pnw 363*4f24fc9aSDan Tang # if nports == (1, 1, 0): 364*4f24fc9aSDan Tang # if masked: 365*4f24fc9aSDan Tang # blackbox = gen_tsmc_ram_2pw("TS6N28HPCPLVTA64X8M2F", width, mask_gran) 366*4f24fc9aSDan Tang # else: 367*4f24fc9aSDan Tang # blackbox = gen_tsmc_ram_2pnw("TS6N28HPCPLVTA64X14M2F") 368*4f24fc9aSDan Tang # elif nports == (0, 0, 1): 369*4f24fc9aSDan Tang # if masked: 370*4f24fc9aSDan Tang # blackbox = gen_tsmc_ram_1pw('TS1N28HPCPLVTB8192X64M8SW', width, mask_gran, addr_width) 371*4f24fc9aSDan Tang # else: 372*4f24fc9aSDan Tang # blackbox = gen_tsmc_ram_1pnw('TS5N28HPCPLVTA64X144M2F', width, addr_width) 373*4f24fc9aSDan Tang # else: 374*4f24fc9aSDan Tang # blackbox = "// unknown tsmc lib type\n" 375*4f24fc9aSDan Tang return mem.generate(blackbox) 376*4f24fc9aSDan Tang 377*4f24fc9aSDan Tang def generate(self, blackbox, itself_only=False): 378*4f24fc9aSDan Tang if itself_only: 379*4f24fc9aSDan Tang # generate splits or reshapes 380*4f24fc9aSDan Tang if self.sub_srams: 381*4f24fc9aSDan Tang return self.mem.generate("") 382*4f24fc9aSDan Tang # use empty blackbox 383*4f24fc9aSDan Tang elif blackbox: 384*4f24fc9aSDan Tang return super().generate(" ") 385*4f24fc9aSDan Tang # insert tsmc libs 386*4f24fc9aSDan Tang else: 387*4f24fc9aSDan Tang return self.__get_tsmc_lib() 388*4f24fc9aSDan Tang else: 389*4f24fc9aSDan Tang s = self.generate(blackbox, True) 390*4f24fc9aSDan Tang for sram in self.sub_srams: 391*4f24fc9aSDan Tang s += sram.generate(blackbox) 392885733f1SZihao Yu return s 393885733f1SZihao Yu 394*4f24fc9aSDan 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): 399*4f24fc9aSDan Tang sram = SRAM(line) 400*4f24fc9aSDan Tang if args.tsmc28: 401*4f24fc9aSDan Tang sram = SRAM_TSMC28(line) 402885733f1SZihao Yu else: 403*4f24fc9aSDan Tang sram = SRAM(line) 404*4f24fc9aSDan Tang if f is not None: 405*4f24fc9aSDan Tang f.write(sram.generate(args.blackbox)) 406*4f24fc9aSDan Tang else: 407*4f24fc9aSDan Tang print(sram.generate(args.blackbox)) 408*4f24fc9aSDan 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') 414*4f24fc9aSDan 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