def default_gen(): from rtl import config try: opts, args = getopt.getopt(sys.argv[1:], "n", [ "hdl=", "name=", "extended", "bram_base=", "path=", "bram_adr_width=" ]) except getopt.GetoptError as err: # print help information and exit: print(err) # will print something like "option -a not recognized" sys.exit(2) name_overide = "" hdl = "VHDL" extended = False bram_base = 0x0 bram_adr_width = 12 gen_path = "vhdl_gen" for o, a in opts: print(o, a) if o in ("-n", "--name"): name_overide = a elif o == "--hdl": hdl = a elif o == "--bram_base": bram_base = int(a, 0) elif o == "--bram_adr_width": bram_adr_width = int(a, 0) elif o == "--extended": extended = True elif o == "--path": gen_path = a if not extended: config = config.BonfireConfig() if name_overide: n = name_overide else: n = "bonfire_core_top" gen_core(config, hdl, n, path) else: config = config.BonfireConfig() if name_overide: n = name_overide else: n = "bonfire_core_extended_top" gen_extended_core(config, hdl, n, gen_path, bram_adr_base=bram_base, bramAdrWidth=bram_adr_width)
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 fusesoc_gen(): import os import yaml from rtl import config CORE_TEMPLATE = """CAPI=2: name: {vlnv} filesets: rtl: file_type: {filetype} files: [ {files} ] targets: default: filesets: [ rtl ] """ print(sys.argv[1]) try: with open(sys.argv[1], mode='r') as f: p = yaml.load(f, Loader=yaml.Loader) print(yaml.dump(p)) files_root = p["files_root"] parameters = p["parameters"] print("Generating into: {}".format(os.getcwd())) hdl = get(parameters, "language", "VHDL") name = get(parameters, "entity_name", "bonfire_core_top") vlnv = p["vlnv"] os.system("rm -f *.vhd *.v *.core") extended = True bram_base = get(parameters, "bram_base", 0x0) bram_adr_width = get(parameters, "bram_adr_width", 12) conversion_warnings = get(parameters, "conversion_warnings", "default") gen_path = os.getcwd() config = config.BonfireConfig() gen_extended_core(config, hdl, name, gen_path, bram_adr_base=bram_base, bramAdrWidth=bram_adr_width, handleWarnings=conversion_warnings) filelist = ["pck_myhdl_011.vhd", name + ".vhd"] with open(name + ".core", "w") as corefile: corefile.write( CORE_TEMPLATE.format(vlnv=vlnv, filetype="vhdlSource-2008", files=",".join(filelist))) return True except FileNotFoundError as err: return False
def pipeline_integration_tests(): print('Testing SimplePipeline with comb shifter') conf=config.BonfireConfig() conf.shifter_mode="comb" test(tb_simple_pipeline.tb(config=conf),trace=False,filename="tb_simple_pipeline_comb_shift") print('Testing SimplePipeline with staged shifter') test(tb_simple_pipeline.tb(test_conversion=False),trace=False,filename="tb_simple_pipeline") print('Testing Fetch unit') test(tb_fetch.tb(test_conversion=False),trace=False,filename="tb_fetch")
def loadstore_unit_tests(): print('Testing Loadstore') conf=config.BonfireConfig() # Waveform tracing test variant conf.loadstore_outstanding=1 conf.registered_read_stage=False test(tb_loadstore.tb(config=conf,test_conversion=False),trace=False,filename="tb_loadstore") # Other variants for i in range(1,3): conf.loadstore_outstanding=i test(tb_loadstore.tb(config=conf,test_conversion=False),trace=False) conf.registered_read_stage=True for i in range(1,4): conf.loadstore_outstanding=i test(tb_loadstore.tb(config=conf,test_conversion=False),trace=False)
def bonfireCoreExtendedInterface(wb_master,db_master,bram_a,bram_b,clock,reset, config=config.BonfireConfig(), wb_mask=AdrMask(32,28,0x2), db_mask=AdrMask(32,28,0x1), bram_mask=AdrMask(32,28,0)): """ wb_master: Wishbone_master_bundle mapped at address 0x02000000 db_master: DbusBundle mapped at address 0x100000000 bram_a: Instruction RamPort32, should be read only, mapped at address 0 bram_b: Data RamPort32 mapped at address 0 clock : cpu clock reset : reset signal wb_mask : Address mask for Wishbone interface db_mask : Address mask for native data bus interface bram_mask : Address mask for Block RAM """ ibus = bonfire_interfaces.DbusBundle(config,readOnly=True) dbus = bonfire_interfaces.DbusBundle(config) control = bonfire_interfaces.ControlBundle(config) debug = bonfire_interfaces.DebugOutputBundle(config) db_master_bram = bonfire_interfaces.DbusBundle(config) # Block RAM db_master_wb = bonfire_interfaces.DbusBundle(config) # Wishbone DBUS ic_class= DbusInterConnects() ic = DbusInterConnects.Master3Slaves(dbus,db_master_bram,db_master_wb,db_master,clock,reset, bram_mask,wb_mask,db_mask) core=bonfire_core_top.BonfireCoreTop(config) core_i = core.createInstance(ibus,dbus,control,clock,reset,debug,config) wb_i = bonfire_interfaces.DbusToWishbone(db_master_wb,wb_master,clock,reset) p_a = dbusToRamPort(ibus,bram_a,clock,readOnly=True) p_b = dbusToRamPort(db_master_bram,bram_b,clock,readOnly=False) return instances()
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()
def __init__(self, config=config.BonfireConfig()): self.config = config self.fetch = FetchUnit(config=config) self.backend_fetch_input = FetchInputBundle(config=config) self.backend_fetch_output = BackendOutputBundle(config=config) self.backend = SimpleBackend(config=config)
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()
""" Simple 3 Stage Pipeline for bonfire_core (c) 2019 The Bonfire Project License: See LICENSE """ from myhdl import * from rtl.decode import * from rtl.execute import * from rtl.regfile import * from rtl import config def_config= config.BonfireConfig() class FetchInputBundle: def __init__(self,config=def_config): self.config=config xlen=config.xlen self.en_i = Signal(bool(0)) # Fetch Data valid/ enable self.word_i = Signal(intbv(0)[xlen:]) # actual instruction to decode self.current_ip_i = Signal(modbv(0)[xlen:]) # ip (PC) of current instruction self.next_ip_i = Signal(modbv(0)[xlen:]) # ip (PC) of next instruction class BackendOutputBundle: def __init__(self,config=def_config): self.config=config xlen=config.xlen
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()