Esempio n. 1
0
def tb(config=config.BonfireConfig(), hexFile="", elfFile="", sigFile=""):

    clock = Signal(bool(0))
    reset = ResetSignal(0, active=1, isasync=False)

    dbus = bonfire_interfaces.DbusBundle(config)
    wb_master = bonfire_interfaces.Wishbone_master_bundle()
    wb_bfm = Wishbone_bfm()

    clk_driver = ClkDriver(clock, period=10)

    bram_port_a = ram_dp.RamPort32(readOnly=True)
    bram_port_b = ram_dp.RamPort32()

    soc_i = bonfire_core_ex.bonfireCoreExtendedInterface(wb_master,
                                                         dbus,
                                                         bram_port_a,
                                                         bram_port_b,
                                                         clock,
                                                         reset,
                                                         config=config)

    ram = ram_dp.DualportedRam(hexFile)
    ram_i = ram.ram_instance(bram_port_a, bram_port_b, clock)

    mon_i = monitor_instance(ram.ram,
                             dbus,
                             clock,
                             sigFile=sigFile,
                             elfFile=elfFile)
    bfm_i = wb_bfm.Wishbone_check(wb_master, clock, reset)

    return instances()
def tb():
    clk_driver = ClkDriver(clock)

    inst = RegisterFile(clock, reg_portA, reg_portB, reg_writePort)
    inst.convert(hdl='VHDL',
                 std_logic_ports=True,
                 path='vhdl_gen',
                 name="regfile")

    @instance
    def stimulus():
        yield clock.posedge

        for i in range(0, 32):
            reg_writePort.wa.next = i
            reg_portA.ra.next = i
            reg_portB.ra.next = i
            reg_writePort.wd.next = 0x55aa0000 | i
            reg_writePort.we.next = 1
            yield clock.posedge

        reg_writePort.we.next = 0
        for i in range(0, 32):
            reg_portA.ra.next = i
            reg_portB.ra.next = i
            yield clock.posedge
            print(reg_portA.rd, reg_portB.rd)

        print("Simulation finished")
        raise StopSimulation

    return instances()
Esempio n. 3
0
def tb_cache_way(test_conversion=False):
    from rtl.cache.cache_way import cache_way_instance, CacheWayBundle
    from rtl.cache.config import CacheConfig

    conf = CacheConfig()
    conf.print_config()

    clock = Signal(bool(0))
    clk_driver = ClkDriver(clock)
    reset = ResetSignal(0, active=1, isasync=False)

    w = CacheWayBundle(conf)

    cw_inst = cache_way_instance(w, clock, reset)
    if test_conversion:
        cw_inst.convert(hdl='VHDL',
                        std_logic_ports=True,
                        path='vhdl_gen',
                        name="cache_way")

    def miss_and_update(adr):
        print("tag miss and update with adr:{}".format(adr))
        conf.print_address(adr)
        w.adr.next = adr
        w.en.next = 1
        yield clock.posedge
        # wait for response
        while not (w.hit or w.miss):
            yield clock.posedge
        assert w.miss and not w.hit, "Miss=1 hit=0 expected"
        assert not w.tag_valid
        assert not w.dirty_miss
        # Write Tag
        w.we.next = True
        w.valid.next = True
        w.dirty.next = True
        yield clock.posedge
        w.we.next = False

        yield clock.posedge

        assert w.tag_valid, "after tag update: tag_valid should be set"
        assert w.hit, "after tag update: hit should be set"
        assert not w.miss, "after tag update: miss should not be set"
        print("OK")

    @instance
    def stimulus():

        yield clock.posedge
        for i in range(0, 16):  #  conf.tag_ram_size):
            adr = conf.create_address(0, i, 0)
            yield miss_and_update(adr)

        raise StopSimulation

    return instances()
Esempio n. 4
0
def tb_barrel_shift_pipelined():

    clk_driver = ClkDriver(clock)
    shift_right = Signal(bool(0))

    dut = barrel_shifter.shift_pipelined(clock, reset, d_in, d_o, shift_in,
                                         shift_right, fill_i, en_i, ready_o, 3)
    dut.convert(hdl='VHDL', std_logic_ports=True, path='vhdl_gen')

    @instance
    def stimulus():

        reset.next = True
        yield delay(40)
        reset.next = False
        yield delay(40)

        print("zero fill")

        fill_i.next = 0
        for i in range(shift_in.max):
            shift_in.next = i

            en_i.next = 1
            yield clock.posedge
            en_i.next = 0

            while ready_o == 0:
                yield clock.posedge

            print(i, bin(d_o, 32))
            assert (d_o == d_in << i)
            yield clock.posedge

        print("Right shift logical")
        d_in.next = 0x80000000
        shift_right.next = True
        for i in range(shift_in.max):
            shift_in.next = i

            en_i.next = 1
            yield clock.posedge
            en_i.next = 0

            while ready_o == 0:
                yield clock.posedge

            print(i, bin(d_o, 32))
            assert (d_o == d_in >> i)
            yield clock.posedge

        print("Simulation finished")
        raise StopSimulation

    return instances()
Esempio n. 5
0
def tb_tagram(test_conversion=False):

    from rtl.cache.cache_way import TagDataBundle
    from rtl.cache.tag_ram import tag_ram_instance

    conf = CacheConfig(**kwargs)

    clock = Signal(bool(0))
    reset = ResetSignal(0, active=1, isasync=False)

    clk_driver = ClkDriver(clock)

    t_in = TagDataBundle(10)
    t_out = TagDataBundle(10)

    we = Signal(bool(0))
    adr = Signal(modbv(0)[conf.line_select_adr_bits:])

    t_r_i = tag_ram_instance(t_in, t_out, we, adr, clock, reset, conf)
    if test_conversion:
        t_r_i.convert(hdl='VHDL',
                      std_logic_ports=True,
                      path='vhdl_gen',
                      name="tag_ram")

    @instance
    def stimulus():

        yield clock.posedge

        # Write data
        we.next = True
        for i in range(0, 16):
            adr.next = i
            t_in.address.next = i
            t_in.valid.next = True
            t_in.dirty.next = False

            yield clock.posedge

        fs = "address: {address}, valid:{valid}, dirty:{dirty} @{adr}"
        we.next = False
        adr.next = 0
        yield clock.posedge

        for i in range(0, 16):
            adr.next = i
            yield clock.posedge
            print(fs.format(adr=adr, **t_out.__dict__))

        print("Simulation finished")
        raise StopSimulation

    return instances()
Esempio n. 6
0
def tb(c_shifter_mode="behavioral", test_conversion=False):

    clk_driver = ClkDriver(clock)

    #inst=alu.alu()
    inst = AluBundle.alu(alu, clock, reset, c_shifter_mode)

    if c_shifter_mode != "behavioral" and test_conversion:
        inst.convert(hdl='VHDL',
                     std_logic_ports=True,
                     path='vhdl_gen',
                     name="alu_" + c_shifter_mode)

    def test_op(cmd):
        alu.funct3_i.next = cmd["f3"]
        alu.funct7_6_i.next = cmd["f7"]
        alu.op1_i.next = cmd["a"]
        alu.op2_i.next = cmd["b"]

        alu.en_i.next = True
        yield clock.posedge
        if not alu.valid_o:
            print(cmd["c"], "pipelined")

        alu.en_i.next = False
        while not alu.valid_o:
            yield clock.posedge
        print("{} {} {} result: {}".format(alu.op1_i, cmd["c"], alu.op2_i,
                                           alu.res_o))
        shouldbe = modbv(0)[32:]
        r = cmd["r"]

        if type(r) == types.FunctionType:
            shouldbe[32:] = r(alu.op1_i, alu.op2_i)
        else:
            shouldbe[32:] = r

        assert alu.res_o == shouldbe, "error, should be {}".format(
            shouldbe.unsigned())

        return

    @instance
    def stimulus():

        yield clock.posedge
        for cmd in commands:
            yield test_op(cmd)

        print("Simulation finished")
        raise StopSimulation

    return instances()
Esempio n. 7
0
def tb(config=config.BonfireConfig(), test_conversion=False):
    clock = Signal(bool(0))
    reset = ResetSignal(0, active=1, isasync=False)
    cmd_index = Signal(intbv(0)[32:])

    debug = DebugOutputBundle(config)
    out = BackendOutputBundle()
    datatbus = loadstore.DbusBundle(config=config)

    backend = SimpleBackend(config=config)
    fetch = FetchInputBundle(config=config)
    frontend = dummy_fetch_unit()
    fu_i = frontend.createInstance(fetch, clock, reset)

    clk_driver = ClkDriver(clock)
    dut = backend.backend(fetch, frontend, datatbus, clock, reset, out, debug)

    if test_conversion:
        dut.convert(hdl='VHDL',
                    std_logic_ports=False,
                    path='vhdl_gen',
                    name="backend")

    # Simulated Data RAM

    mem = sim_ram()
    mem_i = mem.ram_interface(ram, datatbus, clock, reset)

    @always_comb
    def tb_comb():
        result_o.next = debug.result_o
        rd_o.next = debug.rd_adr_o
        we_o.next = debug.reg_we_o
        jump_o.next = backend.execute.jump_o
        jump_dest_o.next = backend.execute.jump_dest_o
        take_branch.next = debug.jump and debug.jump_exec

    def check(cmd):
        t = cmd["t"]
        if type(t) == types.FunctionType:
            if t():
                print("OK")
            else:
                print("FAIL")
                assert StopSimulation
        print("----")

    @always_seq(clock.posedge, reset=reset)
    def commit_check():

        if cmd_index >= len(commands):
            print("Simulation finished")
            raise StopSimulation

        if debug.valid_o:

            cmd = commands[cmd_index]
            if we_o:
                print("at {}ns {}:  commmit to reg {} value {}".format(
                    now(), cmd["source"], abi_name(rd_o), result_o))
            else:
                print("at {}ns {}:  commmit without reg write".format(
                    now(), cmd["source"]))
            check(cmd)

            cmd_index.next = cmd_index + 1

        if debug.jump_exec:
            cmd = commands[cmd_index]
            print("at {}ns: {}, do: {}".format(now(), cmd["source"],
                                               debug.jump))
            check(cmd)
            # In case of a not taken branch increment command counter now, because there will be no jump_o signal
            if not debug.jump:
                cmd_index.next = cmd_index + 1

        if jump_o:
            cmd = commands[cmd_index]
            print("at {}ns: {}, destination: {}".format(
                now(), cmd["source"], jump_dest_o))
            check(cmd)

    return instances()
Esempio n. 8
0
def tb(config=config.BonfireConfig(),test_conversion=False):
    clock=Signal(bool(0))
    reset = ResetSignal(1, active=1, isasync=False)

   
    ibus = DbusBundle(config=config,readOnly=True) 
    debug=DebugOutputBundle(config)
    out = BackendOutputBundle()
    dbus = DbusBundle(config=config) 
    fetch_bundle = FetchInputBundle(config=config)
   
    fetch_unit = FetchUnit(config=config)
    backend = SimpleBackend(config=config)
    

    clk_driver= ClkDriver(clock)
   
    dut=fetch_unit.SimpleFetchUnit(fetch_bundle,ibus,clock,reset)

    if test_conversion:
        dut.convert(hdl='VHDL',std_logic_ports=False,path='vhdl_gen', name="fetch" )


    # processor Backend
    i_backend = backend.backend(fetch_bundle,fetch_unit,dbus,clock,reset,out,debug)

    # Simulated Code RAM 
   
    c_mem = sim_ram()
    c_mem.setLatency(1)
    c_mem_i = c_mem.ram_interface(code_ram,ibus,clock,reset,readOnly=True)

    # Simulated Data RAM
    d_mem = sim_ram()
    d_mem.setLatency(1)
    d_mem_i = d_mem.ram_interface(data_ram,dbus,clock,reset)

    
    @always_comb
    def comb():
        fetch_unit.jump_dest_i.next=out.jump_dest_o
        fetch_unit.jump_i.next = out.jump_o
        fetch_unit.stall_i.next = out.busy_o

        result_o.next =debug.result_o
        rd_o.next = debug.rd_adr_o
        we_o.next = debug.reg_we_o
        jump_o.next = out.jump_o
        jump_dest_o.next = out.jump_dest_o
        take_branch.next = debug.jump and debug.jump_exec


    current_ip_r = Signal(intbv(0))
  
    @always_seq(clock.posedge,reset=reset)
    def sim_observe():

        if backend.execute.taken:
            t_ip = backend.decode.debug_current_ip_o
            print("@{}ns exc: {} : {} ".format(now(),t_ip,backend.decode.debug_word_o))
            assert code_ram[t_ip>>2]==backend.decode.debug_word_o, "pc vs ram content mismatch" 
            assert backend.decode.next_ip_o == t_ip + 4, "next_ip vs. current_ip mismatch" 
            current_ip_r.next = t_ip >> 2
          
        # if out.jump_o:
        #     raise StopSimulation   


   
    jump_cnt = Signal(intbv(0))

    def check(cmd):
        t=cmd["t"]
        if type(t) == types.FunctionType:
            if t():
                print("OK")
            else:
                print("FAIL")
                raise StopSimulation
        print("----")


    @always_seq(clock.posedge,reset=reset)
    def commit_check():

        if jump_cnt > 0:
            print("Simulation finished")
            raise StopSimulation

        if backend.execute.taken:
            idx = backend.decode.debug_current_ip_o >> 2
        else:
            idx = current_ip_r

        if debug.valid_o:    
            cmd = commands[ idx]
            if debug.reg_we_o:
                print("@{}ns {}:  commmit to reg {} value {}".format(now(), cmd["source"], 
                abi_name(debug.rd_adr_o), debug.result_o))
            else:
                print("@{}ns {}:  commmit without reg write".format(now(), cmd["source"]))    
            check(cmd)


        if debug.jump_exec:
            cmd = commands[idx]
            print ("at {}ns: {}, do: {}".format(now(),cmd["source"],debug.jump))
            check(cmd)
            

        if jump_o:
            cmd = commands[idx] 
            print ("at {}ns: {}, destination: {}".format(now(),cmd["source"], jump_dest_o )) 
            jump_cnt.next = jump_cnt + 1
         


    @instance
    def stimulus():
         # Copy code to RAM
        i=0
        for cmd in commands:
            code_ram[i].next=cmd["opcode"]
            i += 1
        for i in range(1,3):    
            yield clock.posedge

        reset.next=0



    return instances()
Esempio n. 9
0
def tb_cache(
        test_conversion=False,
        master_data_width=128,
        line_size=4,  # Line size in MASTER_DATA_WIDTH  words
        cache_size_m_words=2048,  # Cache Size in MASTER_DATA_WIDTH Bit words
        address_bits=30,  #  Number of bits of chacheable address range
        num_ways=1,  # Number of cache ways
        pipelined=False,
        verbose=False):

    from rtl.cache.cache import CacheMasterWishboneBundle, CacheControlBundle, cache_instance
    from rtl.bonfire_interfaces import DbusBundle
    from tb.sim_wb_burst_ram import ram_interface

    config = CacheConfig(master_data_width=master_data_width,
                         line_size=line_size,
                         cache_size_m_words=cache_size_m_words,
                         address_bits=address_bits,
                         num_ways=num_ways)

    clock = Signal(bool(0))
    reset = ResetSignal(0, active=1, isasync=False)
    clk_driver = ClkDriver(clock)

    # our simulated RAM is four times the cache size, this is enough for write testing...
    ram = [
        Signal(modbv(0)[config.master_data_width:])
        for ii in range(0, config.cache_size_m_words * 4)
    ]

    wb_master = CacheMasterWishboneBundle(config)
    db_slave = DbusBundle(len=32)

    pattern_mode = Signal(bool(True))

    ram_i = ram_interface(ram, wb_master, pattern_mode, clock, config)
    c_i = cache_instance(db_slave, wb_master, clock, reset, config)
    if test_conversion:
        c_i.convert(hdl='VHDL',
                    std_logic_ports=True,
                    path='vhdl_gen',
                    name="cache")

    address_queue = []
    queue_len = Signal(intbv(0))

    @always(clock.posedge)
    def monitor_ack():

        if db_slave.ack_i:
            ack_address = address_queue.pop(0)
            queue_len.next = len(address_queue)
            assert queue_len > 0, "ack raised on empy queue"
            if ack_address[2] == "r":
                if verbose:
                    print_t("read_ack: {}:{}".format(ack_address[0],
                                                     db_slave.db_rd))

                if ack_address[1] != None:
                    assert db_slave.db_rd == ack_address[1], \
                      "@{}: read from {}, verify failed expected: {}, read:{}".format(now(),
                            hex(ack_address[0]), hex(ack_address[1]),db_slave.db_rd)
            else:
                if verbose:
                    print_t("write ack at {}:".format(ack_address[0]))

            assert not db_slave.stall_i, "@{} db_slave ack_i while stall_i raised".format(
                now())

    def db_read(address,
                verify=None,
                blocking=False):  # pipelined read start, does not wait on ack

        db_slave.en_o.next = True
        db_slave.we_o.next = 0
        db_slave.adr_o.next = address
        address_queue.append((address, verify, "r"))
        queue_len.next = len(address_queue)
        yield clock.posedge
        # Block on stall
        while db_slave.stall_i:
            yield clock.posedge
        db_slave.en_o.next = False

        if blocking:
            while not db_slave.ack_i:
                yield clock.posedge

    def read_loop(start_adr, length, pipelined=False):

        print("Start loop at:")
        config.print_address(start_adr)

        for i in range(0, length):
            adr = modbv((start_adr + i) << 2)[32:]
            yield db_read(adr, adr, not pipelined)

    def db_write(address, data, blocking=False):
        yield clock.posedge

        db_slave.en_o.next = True
        db_slave.we_o.next = 0b1111
        db_slave.adr_o.next = address
        db_slave.db_wr.next = data
        address_queue.append((address, None, "w"))
        queue_len.next = len(address_queue)
        yield clock.posedge
        # Block on stall
        while db_slave.stall_i:
            yield clock.posedge

        db_slave.en_o.next = False
        db_slave.we_o.next = 0
        if blocking:
            while not db_slave.ack_i:
                yield clock.posedge
                db_slave.en_o.next = False  # deassert en after first clock

    @instance
    def stimulus():
        config.print_config()
        line_size = 2**config.cl_bits_slave  # Line size in slave words

        def loop_test(pipelined):
            print_t("Loop test pipelined" if pipelined else "Loop test")
            for i in range(0, 1):
                yield clock.posedge
                yield clock.posedge

                print_t("Read two lines")
                yield read_loop(config.create_address(0, 0, 0), line_size * 2,
                                pipelined)
                print_t(
                    "Read two lines with same line index, but different tag value"
                )
                yield read_loop(config.create_address(1, 0, 0), line_size * 2,
                                pipelined)

            #print_t("Read from last line of cache")
            #yield read_loop(config.create_address(0,2**config.line_select_adr_bits-1,0),line_size,pipelined)

        def basic_write_test(pipelined):
            blocking = not pipelined

            pattern_mode.next = False
            yield clock.posedge
            print_t("Basic write test")
            yield db_write(0, 0xdeadbeef, blocking)
            yield db_write(4, 0xabcd8000, blocking)

            yield db_read(0, 0xdeadbeef, blocking)
            yield db_read(4, 0xabcd8000, blocking)
            print_t("Write back test")
            adr = config.create_address(1, 0, 0) << 2
            yield db_write(adr, 0x55aa55ff, blocking)
            yield db_read(adr, 0x55aa55ff, blocking)
            print_t("cross check")
            yield db_read(0, 0xdeadbeef, blocking)

        yield clock.posedge
        yield db_read(0xc, 0xc, not pipelined)
        yield loop_test(pipelined)
        yield basic_write_test(pipelined)

        yield clock.posedge
        raise StopSimulation

    return instances()
Esempio n. 10
0
def tb(test_conversion=False):

    clk_driver = ClkDriver(clock)

    inst = DecodeBundle.decoder(dec, clock, reset)

    if test_conversion:
        inst.convert(hdl='VHDL',
                     std_logic_ports=True,
                     path='vhdl_gen',
                     name="decode")

    cmd_index = Signal(intbv(0))

    rs1 = Signal(intbv(0)[5:])
    rs2 = Signal(intbv(0)[5:])

    @always_seq(clock.posedge, reset=reset)
    def decode_output():

        # Save register addresses
        if dec.en_i:
            rs1.next = dec.rs1_adr_o
            rs2.next = dec.rs2_adr_o

        if dec.valid_o:

            if cmd_index >= len(commands):
                print("Simulation finished")
                raise StopSimulation

            cmd = commands[cmd_index]
            print("{} at {} ns".format(cmd["source"], now()))
            print("rs1: {}, rs2: {} rd:{}".format(abi_name(rs1), abi_name(rs2),
                                                  abi_name(dec.rd_adr_o)))
            print("funct3: {} funct7: {}".format(bin(dec.funct3_onehot_o, 8),
                                                 bin(dec.funct7_o, 7)))
            print("op1: {} op2: {}".format(dec.op1_o, dec.op2_o, 7))

            if dec.branch_cmd:
                print("Branch target: {}".format(hex(dec.jump_dest_o)))

            t = cmd["t"]

            if type(t) == types.FunctionType:
                if t(dec, rs1, rs2):
                    print("OK")
                else:
                    print("FAIL")
            print("----")

            cmd_index.next = cmd_index + 1

    def test_op(cmd):

        dec.word_i.next = cmd["opcode"]
        ip = cmd.get("current_ip", 0)
        dec.current_ip_i.next = ip
        dec.next_ip_i.next = ip + 4

        dec.en_i.next = True
        yield clock.posedge

        return

    @instance
    def stimulus():

        for cmd in commands:
            yield test_op(cmd)

    return instances()
def tb(config=config.BonfireConfig(),test_conversion=False):

    print("Testing LSU with loadstore_outstanding={}, registered_read_stage={} ".format(config.loadstore_outstanding,config.registered_read_stage))
    clock=Signal(bool(0))
    reset = ResetSignal(0, active=1, isasync=False)

    clk_driver= ClkDriver(clock)

   
    bus = DbusBundle(config)
    ls = LoadStoreBundle(config)

    dut=LoadStoreBundle.LoadStoreUnit(ls,bus,clock,reset)

    if test_conversion:
        dut.convert(hdl='VHDL',std_logic_ports=False,path='vhdl_gen', name="loadstore" )


    ram = [Signal(modbv(0)[32:]) for ii in range(0, ram_size)]
    mem = sim_ram()
    mem_i = mem.ram_interface(ram,bus,clock,reset)

    cnt = Signal(intbv(0))

    fetch_index = Signal(intbv(0))
    
    def sw_test():
        fetch_index.next = 0
        yield clock.posedge

        ls.funct3_i.next = StoreFunct3.RV32_F3_SW
        ls.store_i.next = True
        ls.op1_i.next = 0
        ls.rd_i.next = 5

        countdown=len(store_words)

        while countdown>0:

            if ls.valid_o:
                countdown -= 1

            if fetch_index<len(store_words):
                ls.en_i.next = True
                if not ls.busy_o:
                    ls.displacement_i.next = fetch_index * 4
                    ls.op2_i.next = store_words[fetch_index]
                    fetch_index.next += 1

            else:
                if not ls.busy_o:   
                    ls.en_i.next=False    

            yield clock.posedge

        # Verify memory content 
        i=0
        for v in store_words:
            print("write check ram[{}]: {}=={} ".format(i,ram[i],hex(v)))
            assert ram[i]==v, "loadstore sw test failed"
            i += 1

   

    def lw_test():
        yield clock.posedge
        ls.funct3_i.next = LoadFunct3.RV32_F3_LW
        ls.store_i.next= False
        ls.op1_i.next=0
       
        count=len(store_words)
        finish=False
        i=Signal(intbv(0))

        while not finish:
            if not ls.busy_o:
                ls.displacement_i.next= i*4
                ls.rd_i.next= i # "Misuse" rd register as index into test data
                i.next +=  1
                ls.en_i.next = i<count 
                
            if ls.valid_o:
                assert ls.we_o, "loadstore lw test, ls.we_o not set"
                print("read check x{}: {} == {}".format(ls.rd_o,ls.result_o,hex(store_words[ls.rd_o])))
                assert(ls.result_o==store_words[ls.rd_o]), "loadstore lw test failed"
                finish = ls.rd_o==count-1
            
            yield clock.posedge            


    def sb_test():
        yield clock.posedge
        ls.funct3_i.next = StoreFunct3.RV32_F3_SB
        ls.store_i.next = True
        ls.op1_i.next = 5<<2 # Base Memory address for test
        ls.rd_i.next = 5

        countdown=8
        displacement=0

        while countdown>0:

            if ls.valid_o:
                countdown -=  1

            if displacement<8:
                ls.en_i.next = True
                if not ls.busy_o:
                    ls.displacement_i.next = displacement
                    # Extract next byte from store_words 
                    ls.op2_i.next = store_words[displacement>>2] >> (displacement % 4* 8)
                    displacement += 1

            else:
                if not ls.busy_o:   
                    ls.en_i.next=False    

            yield clock.posedge

        print("Store Byte result: {} {}".format(ram[5],ram[6]))
        assert (ram[5]==store_words[0] and ram[6]==store_words[1]), "loadstore sb test failed"


    def sh_test():
        yield clock.posedge
        ls.funct3_i.next = StoreFunct3.RV32_F3_SH
        ls.store_i.next = True
        ls.op1_i.next = 7<<2 # Base Memory address for test
        ls.rd_i.next = 5

        countdown=4
        displacement=0

        while countdown>0:

            if ls.valid_o:
                countdown -= 1

            if displacement<8:
                ls.en_i.next = True
                if not ls.busy_o:
                    ls.displacement_i.next = displacement
                    # Extract next half word from store_words 
                    ls.op2_i.next = store_words[displacement>>2] >> ((displacement >> 1 & 1)  * 16)
                    displacement +=  2

            else:
                if not ls.busy_o:   
                    ls.en_i.next=False    

            yield clock.posedge

        print("Store word result: {} {}".format(ram[7],ram[8]))
        assert(ram[7]==store_words[0] and ram[8]==store_words[1]), "loadstore sh test failed"


    def load_single(base,displacement,funct3): 
        ls.funct3_i.next = funct3
        ls.store_i.next = False
        ls.op1_i.next = base 
        ls.rd_i.next = 5
        ls.displacement_i.next = displacement
        ls.en_i.next = True
        yield clock.posedge
        while ls.busy_o:
            yield clock.posedge
        ls.en_i.next = False 

        while not ls.valid_o:
            yield clock.posedge
        print(now())

    def wait_valid():
         while ls.valid_o:
           yield clock.posedge

       

    def _check(a,b,message):
       s= "{}: checking {}=={}".format(message,hex(a),hex(b))
       assert a==b, s + " failed"
       print(s," OK")

    def _check_we():
        assert ls.we_o,"Register we signal not set"

    def load_other_test():
        """
        Test lb,lbu,lh,lhu
        """
        assert ram[3]==0x705a8000, "load_other:  ram[3] does not contain the expected content"
        yield clock.posedge

        print("Testing lbu")
        yield load_single(3<<2,1,LoadFunct3.RV32_F3_LBU) ## Should read the ff byte 
        _check_we()
        _check(ls.result_o,0x80,"lbu test" )
       
        print("Testing lb negative")
        yield load_single(3<<2,1,LoadFunct3.RV32_F3_LB) ## Should read and sign extend the ff byte 
        _check_we()
        _check(ls.result_o,0xffffff80,"lb negative test" )
       
        print("Testing lb positive")
        yield load_single(3<<2,2,LoadFunct3.RV32_F3_LB) ## Should read and sign extend the 55 byte 
        _check_we()
        _check(ls.result_o,0x5a,"lb positive test" )

        print("Testing lhu")
        yield load_single(3<<2,0,LoadFunct3.RV32_F3_LHU) ## Should read the ff00 hword 
        _check_we()
        _check(ls.result_o,0x8000,"lhu test" )

        print("Testing lh negative")
        yield load_single(3<<2,0,LoadFunct3.RV32_F3_LH) ## Should read and sign extend the ff00 hword 
        _check_we()
        _check(ls.result_o,0xffff8000,"lh negative test" )

        print("Testing lh positive")
        yield load_single(3<<2,2,LoadFunct3.RV32_F3_LH) ## Should read and sign extend the 0055 hword 
        _check_we()
        _check(ls.result_o,0x705a,"lh positive test" )


    def run_all():
       yield sw_test()
       yield wait_valid()
      
       yield lw_test()
       yield wait_valid()
       yield sb_test()   
       yield wait_valid() 
       yield sh_test()
       yield wait_valid()
       yield load_other_test()


    def clear_ram():
        for m in ram:
           m.next = 0
        yield clock.posedge


        
    
    @instance
    def stimulus():
      

       mem.setLatency(1) 
       yield run_all()
       yield clear_ram()
       print("Run with RAM wait state")
       mem.setLatency(2) 
       yield run_all()
       raise StopSimulation
         

    return instances()