diff --git a/fuzzers/036-iob-ologic/generate.py b/fuzzers/036-iob-ologic/generate.py index 63342d12..d9445a5c 100644 --- a/fuzzers/036-iob-ologic/generate.py +++ b/fuzzers/036-iob-ologic/generate.py @@ -5,6 +5,13 @@ from prjxray import verilog import json +def bitfilter(frame, word): + if frame < 30 or frame > 37: + return False + + return True + + def handle_data_width(segmk, d): if 'DATA_WIDTH' not in d: return @@ -31,6 +38,7 @@ def main(): handle_data_width(segmk, d) if d['use_oserdese2']: + segmk.add_site_tag(site, 'OQUSED', 1) if 'SRTYPE' in d: for opt in ['ASYNC', 'SYNC']: segmk.add_site_tag( @@ -47,41 +55,53 @@ def main(): site, 'OSERDESE.DATA_RATE_TQ.{}'.format(opt), verilog.unquote(d['DATA_RATE_TQ']) == opt) - if d['oddr_mux_config'] != 'none': - segmk.add_site_tag(site, 'OFF.ZINIT_Q', not d['QINIT']) + for opt in ['SRVAL_OQ', 'SRVAL_TQ', 'INIT_OQ', 'INIT_TQ']: + segmk.add_site_tag(site, opt, d[opt]) + segmk.add_site_tag(site, 'Z' + opt, 1 ^ d[opt]) + + for opt in ['CLK', 'CLKDIV']: + k = 'IS_{}_INVERTED'.format(opt) + segmk.add_site_tag(site, k, d[k]) + segmk.add_site_tag(site, 'ZINV_{}'.format(opt), 1 ^ d[k]) + + for idx in range(4): + k = 'IS_T{}_INVERTED'.format(idx + 1) + segmk.add_site_tag(site, k, d[k]) + segmk.add_site_tag( + site, 'ZINV_T{}'.format(idx + 1), 1 ^ d[k]) + + for idx in range(8): + k = 'IS_D{}_INVERTED'.format(idx + 1) + segmk.add_site_tag(site, k, d[k]) + segmk.add_site_tag( + site, 'ZINV_D{}'.format(idx + 1), 1 ^ d[k]) + + if d['oddr_mux_config'] == 'direct' and d[ + 'tddr_mux_config'] == 'direct': for opt in ['OPPOSITE_EDGE', 'SAME_EDGE']: segmk.add_site_tag( site, 'ODDR.DDR_CLK_EDGE.{}'.format(opt), verilog.unquote(d['ODDR_CLK_EDGE']) == opt) - if d['tddr_mux_config'] != 'none': - segmk.add_site_tag(site, 'TFF.ZINIT_Q', not d['TINIT']) - # Note: edge settings seem to be ignored for TFF - for opt in ['OPPOSITE_EDGE', 'SAME_EDGE']: - segmk.add_site_tag( - site, 'TDDR.DDR_CLK_EDGE.{}'.format(opt), - verilog.unquote(d['TDDR_CLK_EDGE']) != opt) + segmk.add_site_tag( + site, 'TDDR.DDR_CLK_EDGE.INV', + d['ODDR_CLK_EDGE'] != d['TDDR_CLK_EDGE']) + segmk.add_site_tag( + site, 'TDDR.DDR_CLK_EDGE.ZINV', + d['ODDR_CLK_EDGE'] == d['TDDR_CLK_EDGE']) - # all the bellow mux configs give 0 candidates - # this is wierd, as they are set when DDR output is used - # something's fishy here - if d['oddr_mux_config'] == 'direct': - segmk.add_site_tag(site, 'OMUXE2', 0) + if not d['use_oserdese2']: + if d['oddr_mux_config'] == 'lut': + segmk.add_site_tag(site, 'OMUX.D1', 1) + segmk.add_site_tag(site, 'OQUSED', 1) + elif d['oddr_mux_config'] == 'direct': + segmk.add_site_tag(site, 'OMUX.D1', 0) + elif d['oddr_mux_config'] == 'none' and not d['io']: + segmk.add_site_tag(site, 'OQUSED', 0) - elif d['oddr_mux_config'] == 'none': - segmk.add_site_tag(site, 'OMUXE2', 1) - else: - assert False, d['oddr_mux_config'] + segmk.add_site_tag(site, 'TQUSED', d['io']) - if d['tddr_mux_config'] == 'direct': - segmk.add_site_tag(site, 'TMUXE2', 0) - - elif d['tddr_mux_config'] == 'none': - segmk.add_site_tag(site, 'TMUXE2', 1) - else: - assert False, d['tddr_mux_config'] - - segmk.compile() + segmk.compile(bitfilter=bitfilter) segmk.write(allow_empty=True) diff --git a/fuzzers/036-iob-ologic/top.py b/fuzzers/036-iob-ologic/top.py index 9e4d07ca..2407fcf9 100644 --- a/fuzzers/036-iob-ologic/top.py +++ b/fuzzers/036-iob-ologic/top.py @@ -69,6 +69,40 @@ def use_oserdese2(p, luts, connects): p['TRISTATE_WIDTH'] = tristate_width p['OSERDES_MODE'] = verilog.quote(random.choice(('MASTER', 'SLAVE'))) + if p['io']: + p['TFB'] = '.TFB(tfb_{site}),'.format(**p) + p['TQ'] = '.TQ({twire}),'.format(**p) + p['t1net'] = luts.get_next_output_net() + p['t2net'] = luts.get_next_output_net() + p['t3net'] = luts.get_next_output_net() + p['t4net'] = luts.get_next_output_net() + p['tcenet'] = luts.get_next_output_net() + + for idx in range(4): + p['IS_T{}_INVERTED'.format(idx + 1)] = random.randint(0, 1) + else: + p['TFB'] = '.TFB(),' + p['TQ'] = '.TQ(),' + p['t1net'] = '' + p['t2net'] = '' + p['t3net'] = '' + p['t4net'] = '' + p['tcenet'] = '' + + for idx in range(4): + p['IS_T{}_INVERTED'.format(idx + 1)] = 0 + + p['SRVAL_OQ'] = random.randint(0, 1) + p['SRVAL_TQ'] = random.randint(0, 1) + p['INIT_OQ'] = random.randint(0, 1) + p['INIT_TQ'] = random.randint(0, 1) + + for idx in range(8): + p['IS_D{}_INVERTED'.format(idx + 1)] = random.randint(0, 1) + + p['IS_CLK_INVERTED'] = random.randint(0, 1) + p['IS_CLKDIV_INVERTED'] = random.randint(0, 1) + print( ''' (* KEEP, DONT_TOUCH, LOC = "{ologic_loc}" *) @@ -77,11 +111,29 @@ def use_oserdese2(p, luts, connects): .DATA_RATE_TQ({DATA_RATE_TQ}), .DATA_RATE_OQ({DATA_RATE_OQ}), .DATA_WIDTH({DATA_WIDTH}), - .TRISTATE_WIDTH({TRISTATE_WIDTH}) + .TRISTATE_WIDTH({TRISTATE_WIDTH}), + .SRVAL_OQ({SRVAL_OQ}), + .SRVAL_TQ({SRVAL_TQ}), + .INIT_OQ({INIT_OQ}), + .INIT_TQ({INIT_TQ}), + .IS_T1_INVERTED({IS_T1_INVERTED}), + .IS_T2_INVERTED({IS_T2_INVERTED}), + .IS_T3_INVERTED({IS_T3_INVERTED}), + .IS_T4_INVERTED({IS_T4_INVERTED}), + .IS_D1_INVERTED({IS_D1_INVERTED}), + .IS_D2_INVERTED({IS_D2_INVERTED}), + .IS_D3_INVERTED({IS_D3_INVERTED}), + .IS_D4_INVERTED({IS_D4_INVERTED}), + .IS_D5_INVERTED({IS_D5_INVERTED}), + .IS_D6_INVERTED({IS_D6_INVERTED}), + .IS_D7_INVERTED({IS_D7_INVERTED}), + .IS_D8_INVERTED({IS_D8_INVERTED}), + .IS_CLK_INVERTED({IS_CLK_INVERTED}), + .IS_CLKDIV_INVERTED({IS_CLKDIV_INVERTED}) ) oserdese2_{site} ( .OQ({owire}), - .TFB(tfb_{site}), - .TQ({twire}), + {TFB} + {TQ} .CLK({clknet}), .CLKDIV({clkdivnet}), .D1({d1net}), @@ -111,11 +163,6 @@ def use_oserdese2(p, luts, connects): d6net=luts.get_next_output_net(), d7net=luts.get_next_output_net(), d8net=luts.get_next_output_net(), - t1net=luts.get_next_output_net(), - t2net=luts.get_next_output_net(), - t3net=luts.get_next_output_net(), - t4net=luts.get_next_output_net(), - tcenet=luts.get_next_output_net(), ocenet=luts.get_next_output_net(), ofb_wire=luts.get_next_input_net(), **p), @@ -125,18 +172,30 @@ def use_oserdese2(p, luts, connects): def use_direct_and_oddr(p, luts, connects): p['oddr_mux_config'] = random.choice(( 'direct', + 'lut', 'none', )) - p['tddr_mux_config'] = random.choice(( - 'direct', - 'none', - )) + if p['io']: + if p['oddr_mux_config'] != 'lut': + p['tddr_mux_config'] = random.choice(( + 'direct', + 'lut', + 'none', + )) + else: + p['tddr_mux_config'] = random.choice(( + 'lut', + 'none', + )) + else: + p['tddr_mux_config'] = 'none' # toddr and oddr share the same clk clknet = luts.get_next_output_net() + p['IS_CLK_INVERTED'] = 0 - if p['tddr_mux_config'] != 'none': + if p['tddr_mux_config'] == 'direct': p['TINIT'] = random.randint(0, 1) p['TSRTYPE'] = verilog.quote(random.choice(('SYNC', 'ASYNC'))) p['TDDR_CLK_EDGE'] = verilog.quote('OPPOSITE_EDGE') @@ -150,7 +209,8 @@ def use_direct_and_oddr(p, luts, connects): ODDR #( .INIT({TINIT}), .SRTYPE({TSRTYPE}), - .DDR_CLK_EDGE({TDDR_CLK_EDGE}) + .DDR_CLK_EDGE({TDDR_CLK_EDGE}), + .IS_C_INVERTED({IS_CLK_INVERTED}) ) toddr_{site} ( .C({cnet}), .D1({d1net}), @@ -171,12 +231,18 @@ def use_direct_and_oddr(p, luts, connects): ''' assign {twire} = tddr_d_{site};'''.format(**p, ), file=connects) + elif p['tddr_mux_config'] == 'lut': + print( + ''' + assign {twire} = {lut};'''.format(lut=luts.get_next_output_net(), **p), + file=connects) + pass elif p['tddr_mux_config'] == 'none': pass else: assert False, p['tddr_mux_config'] - if p['oddr_mux_config'] != 'none': + if p['oddr_mux_config'] == 'direct': p['QINIT'] = random.randint(0, 1) p['SRTYPE'] = verilog.quote(random.choice(('SYNC', 'ASYNC'))) p['ODDR_CLK_EDGE'] = verilog.quote( @@ -191,7 +257,8 @@ def use_direct_and_oddr(p, luts, connects): ODDR #( .INIT({QINIT}), .SRTYPE({SRTYPE}), - .DDR_CLK_EDGE({ODDR_CLK_EDGE}) + .DDR_CLK_EDGE({ODDR_CLK_EDGE}), + .IS_C_INVERTED({IS_CLK_INVERTED}) ) oddr_{site} ( .C({cnet}), .D1({d1net}), @@ -212,6 +279,12 @@ def use_direct_and_oddr(p, luts, connects): ''' assign {owire} = oddr_d_{site};'''.format(**p, ), file=connects) + elif p['oddr_mux_config'] == 'lut': + print( + ''' + assign {owire} = {lut};'''.format(lut=luts.get_next_output_net(), **p), + file=connects) + pass elif p['oddr_mux_config'] == 'none': pass else: @@ -240,6 +313,9 @@ def run(): tile_params = [] params = [] + + ndio = 0 + ndo = 0 for idx, (tile, site) in enumerate(gen_sites()): if idx == 0: continue @@ -254,10 +330,18 @@ def run(): p['DRIVE'] = random.choice(drives) p['SLEW'] = verilog.quote(random.choice(slews)) - p['pad_wire'] = 'dio[{}]'.format(idx - 1) + p['io'] = random.randint(0, 1) p['owire'] = 'do_buf[{}]'.format(idx - 1) - p['iwire'] = 'di_buf[{}]'.format(idx - 1) - p['twire'] = 't[{}]'.format(idx - 1) + + if p['io']: + p['pad_wire'] = 'dio[{}]'.format(ndio) + ndio += 1 + + p['iwire'] = 'di_buf[{}]'.format(idx - 1) + p['twire'] = 't[{}]'.format(idx - 1) + else: + p['pad_wire'] = 'do[{}]'.format(ndo) + ndo += 1 params.append(p) tile_params.append( @@ -270,13 +354,14 @@ def run(): print( ''' -`define N_DI {n_di} +`define N_DO {n_do} +`define N_DIO {n_dio} -module top(input clk, inout wire [`N_DI-1:0] dio); - wire [`N_DI-1:0] di_buf; - wire [`N_DI-1:0] do_buf; - wire [`N_DI-1:0] t; - '''.format(n_di=idx)) +module top(input clk, output wire [`N_DO-1:0] do, inout wire [`N_DIO-1:0] dio); + wire [(`N_DIO+`N_DO)-1:0] di_buf; + wire [(`N_DIO+`N_DO)-1:0] do_buf; + wire [(`N_DIO+`N_DO)-1:0] t; + '''.format(n_dio=ndio, n_do=ndo)) # Always output a LUT6 to make placer happy. print( @@ -286,8 +371,9 @@ module top(input clk, inout wire [`N_DI-1:0] dio); ''') for p in params: - print( - ''' + if p['io']: + print( + ''' wire oddr_d_{site}; (* KEEP, DONT_TOUCH, LOC = "{site}" *) @@ -300,7 +386,21 @@ module top(input clk, inout wire [`N_DI-1:0] dio); .T({twire}) ); '''.format(**p), - file=connects) + file=connects) + else: + print( + ''' + wire oddr_d_{site}; + + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + OBUF #( + .IOSTANDARD({IOSTANDARD}) + ) obuf_{site} ( + .O({pad_wire}), + .I({owire}) + ); + '''.format(**p), + file=connects) p['use_oserdese2'] = random.randint(0, 1) if p['use_oserdese2']: