@@ -43,6 +43,7 @@ class Stream(BaseStream):
4343 'set_sink' , 'set_sink_pattern' , 'set_sink_multidim' ,
4444 'set_sink_multipattern' , 'set_sink_immediate' ,
4545 'set_sink_empty' , 'set_constant' ,
46+ 'set_read_RAM' ,
4647 'read_sink' ,
4748 'run' , 'join' , 'done' ,
4849 'source_join' , 'source_done' ,
@@ -100,6 +101,7 @@ def __init__(self, m, name, clk, rst,
100101 self .sinks = OrderedDict ()
101102 self .constants = OrderedDict ()
102103 self .substreams = []
104+ self .read_rams = OrderedDict ()
103105
104106 self .var_name_map = OrderedDict ()
105107 self .var_id_map = OrderedDict ()
@@ -334,6 +336,40 @@ def substream(self, substrm):
334336 self .substreams .append (sub )
335337 return sub
336338
339+ def read_RAM (self , name , addr , datawidth = None , point = 0 , signed = True ):
340+ if self .stream_synthesized :
341+ raise ValueError (
342+ 'cannot modify the stream because already synthesized' )
343+
344+ _id = self .var_id_count
345+ if name is None :
346+ name = 'read_ram_%d' % _id
347+
348+ if name in self .var_name_map :
349+ raise ValueError ("'%s' is already defined in stream '%s'" %
350+ (name , self .name ))
351+
352+ prefix = self ._prefix (name )
353+
354+ self .var_id_count += 1
355+
356+ if datawidth is None :
357+ datawidth = self .datawidth
358+
359+ var = self .ReadRAM (addr , width = datawidth , point = point , signed = signed , ram_name = name )
360+
361+ self .read_rams [name ] = var
362+ self .var_id_map [_id ] = var
363+ self .var_name_map [name ] = var
364+ self .var_id_name_map [_id ] = name
365+ self .var_name_id_map [name ] = _id
366+
367+ var .read_ram_id_map = OrderedDict ()
368+ var .read_ram_sel = self .module .Reg ('_%s_read_ram_sel' % prefix ,
369+ self .ram_sel_width , initval = 0 )
370+
371+ return var
372+
337373 def set_source (self , fsm , name , ram , offset , size , stride = 1 , port = 0 ):
338374 """ intrinsic method to assign RAM property to a source stream """
339375
@@ -906,6 +942,35 @@ def set_constant(self, fsm, name, value, raw=False):
906942
907943 fsm .goto_next ()
908944
945+ def set_read_RAM (self , fsm , name , ram , port = 0 ):
946+ """ intrinsic method to assign RAM property to a read-RAM interface """
947+
948+ if not self .stream_synthesized :
949+ self ._implement_stream ()
950+
951+ if isinstance (name , str ):
952+ var = self .var_name_map [name ]
953+ elif isinstance (name , vtypes .Str ):
954+ name = name .value
955+ var = self .var_name_map [name ]
956+ elif isinstance (name , int ):
957+ var = self .var_id_map [name ]
958+ elif isinstance (name , vtypes .Int ):
959+ name = name .value
960+ var = self .var_id_map [name ]
961+ else :
962+ raise TypeError ('Unsupported index name' )
963+
964+ if name not in self .read_rams :
965+ raise NameError ("No such stream '%s'" % name )
966+
967+ set_cond = self ._set_flag (fsm )
968+
969+ port = vtypes .to_int (port )
970+ self ._setup_read_ram (ram , var , port , set_cond )
971+
972+ fsm .goto_next ()
973+
909974 def read_sink (self , fsm , name ):
910975 """ intrinsic method to read the last output of a sink stream """
911976
@@ -2110,6 +2175,119 @@ def _synthesize_set_sink_multipattern(self, var, name):
21102175 var .sink_multipat_num_patterns == 0 ).goto_init ()
21112176 var .sink_multipat_fsm .If (self .term_sink ).goto_init ()
21122177
2178+ def _setup_read_ram (self , ram , var , port , set_cond ):
2179+ if ram ._id () in var .read_ram_id_map :
2180+ ram_id = var .read_ram_id_map [ram ._id ()]
2181+ self .seq .If (set_cond )(
2182+ var .read_ram_sel (ram_id )
2183+ )
2184+ return
2185+
2186+ if ram ._id () not in self .ram_id_map :
2187+ ram_id = self .ram_id_count
2188+ self .ram_id_count += 1
2189+ self .ram_id_map [ram ._id ()] = ram_id
2190+ else :
2191+ ram_id = self .ram_id_map [ram ._id ()]
2192+
2193+ var .read_ram_id_map [ram ._id ()] = ram_id
2194+
2195+ self .seq .If (set_cond )(
2196+ var .read_ram_sel (ram_id )
2197+ )
2198+
2199+ ram_cond = (var .read_ram_sel == ram_id )
2200+ renable = vtypes .Ands (var .enable , ram_cond )
2201+
2202+ d , v = ram .read_rtl (var .addr , port = port , cond = renable )
2203+ add_mux (var .read_data , ram_cond , d )
2204+
2205+ if (self .dump and
2206+ (self .dump_mode == 'all' or
2207+ self .dump_mode == 'ram' or
2208+ (self .dump_mode == 'selective' and
2209+ hasattr (ram , 'dump' ) and ram .dump ))):
2210+ self ._setup_read_ram_dump (ram , var , renable , d )
2211+
2212+ def _setup_read_ram_dump (self , ram , var , read_enable , read_data ):
2213+ pipeline_depth = self .pipeline_depth ()
2214+ log_pipeline_depth = max (
2215+ int (math .ceil (math .log (max (pipeline_depth , 10 ), 10 ))), 1 )
2216+
2217+ addr_base = (ram .dump_addr_base if hasattr (ram , 'dump_addr_base' ) else
2218+ self .dump_base )
2219+ addr_base_char = ('b' if addr_base == 2 else
2220+ 'o' if addr_base == 8 else
2221+ 'd' if addr_base == 10 else
2222+ 'x' )
2223+ addr_prefix = ('0b' if addr_base == 2 else
2224+ '0o' if addr_base == 8 else
2225+ ' ' if addr_base == 10 else
2226+ '0x' )
2227+ addr_vfmt = '' .join ([addr_prefix , '%' , addr_base_char ])
2228+
2229+ data_base = (ram .dump_data_base if hasattr (ram , 'dump_data_base' ) else
2230+ self .dump_base )
2231+ data_base_char = ('b' if data_base == 2 else
2232+ 'o' if data_base == 8 else
2233+ 'd' if (data_base == 10 and
2234+ (not hasattr (ram , 'point' ) or ram .point <= 0 )) else
2235+ # 'f' if (data_base == 10 and
2236+ # hasattr(ram, 'point') and ram.point > 0) else
2237+ 'g' if (data_base == 10 and
2238+ hasattr (ram , 'point' ) and ram .point > 0 ) else
2239+ 'x' )
2240+ data_prefix = ('0b' if data_base == 2 else
2241+ '0o' if data_base == 8 else
2242+ ' ' if data_base == 10 else
2243+ '0x' )
2244+ # if data_base_char == 'f':
2245+ # point_len = int(math.ceil(ram.point / math.log(10, 2)))
2246+ # point_len = max(point_len, 8)
2247+ # total_len = int(math.ceil(ram.datawidth / math.log(10, 2)))
2248+ # total_len = max(total_len, point_len)
2249+ # data_vfmt = ''.join([data_prefix, '%',
2250+ # '%d.%d' % (total_len + 1, point_len),
2251+ # data_base_char])
2252+ # else:
2253+ # data_vfmt = ''.join([data_prefix, '%', data_base_char])
2254+ data_vfmt = '' .join ([data_prefix , '%' , data_base_char ])
2255+
2256+ name = ram .name
2257+ fmt = '' .join (['(' , self .name , ' step:%d, ' ,
2258+ 'read, ' , ' ' * (log_pipeline_depth + 2 ),
2259+ 'age:%d) ' , name ,
2260+ '[' , addr_vfmt , '] = ' , data_vfmt ])
2261+
2262+ dump_ram_step_name = ('_stream_dump_ram_step_%d_%s' %
2263+ (self .object_id , name ))
2264+ dump_ram_step = self .module .Reg (dump_ram_step_name , 32 , initval = 0 )
2265+
2266+ enable = self .seq .Prev (read_enable , 2 )
2267+ age = dump_ram_step
2268+ addr = self .seq .Prev (var .addr , 2 )
2269+ if hasattr (ram , 'point' ) and ram .point > 0 :
2270+ data = vtypes .Div (vtypes .SystemTask ('itor' , read_data ),
2271+ 1.0 * (2 ** ram .point ))
2272+ elif hasattr (ram , 'point' ) and ram .point < 0 :
2273+ data = vtypes .Times (read_data , 2 ** - ram .point )
2274+ else :
2275+ data = read_data
2276+
2277+ self .seq (
2278+ dump_ram_step (0 )
2279+ )
2280+ self .seq .If (enable )(
2281+ dump_ram_step .inc ()
2282+ )
2283+ self .seq .If (self .dump_enable )(
2284+ dump_ram_step .inc ()
2285+ )
2286+
2287+ self .seq .If (enable , vtypes .Not (self .dump_mask ))(
2288+ vtypes .Display (fmt , dump_ram_step , age , addr , data )
2289+ )
2290+
21132291 def _set_flag (self , fsm , prefix = '_set_flag' ):
21142292 flag = self .module .TmpReg (initval = 0 , prefix = prefix )
21152293 cond = fsm .here
@@ -2166,7 +2344,8 @@ def __getattr__(self, attr):
21662344 f .__name__ .startswith ('Counter' ) or
21672345 f .__name__ .startswith ('Pulse' ) or
21682346 f .__name__ .startswith ('RingBuffer' ) or
2169- f .__name__ .startswith ('Scratchpad' ))):
2347+ f .__name__ .startswith ('Scratchpad' ) or
2348+ f .__name__ .startswith ('ReadRAM' ))):
21702349 if self .reduce_reset is None :
21712350 self .reduce_reset = self .module .Reg (
21722351 '_' .join (['' , self .name , 'reduce_reset' ]), initval = 1 )
0 commit comments