From 7a489b3135f413c3a61240581cf85257343e36c4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 18 Apr 2014 10:33:05 +0200 Subject: [PATCH] refactor code --- doc/.keep_me | 0 examples/de0_nano/Makefile | 12 -- examples/de0_nano/client/test_miio.py | 57 ----- examples/de0_nano/client/test_mila.py | 99 --------- examples/de0_nano/make.py | 42 ---- examples/de0_nano/timings.py | 29 --- examples/de0_nano/top.py | 106 --------- miscope/com/uart2csr/__init__.py | 180 ---------------- miscope/com/uart2csr/host/__init__.py | 0 miscope/com/uart2csr/host/uart2csr.py | 91 -------- miscope/com/uart2csr/uart.py | 107 ---------- miscope/com/uart2wb/__init__.py | 0 miscope/com/uart2wb/host/__init__.py | 0 miscope/com/uart2wb/host/uart2wb.py | 89 -------- miscope/com/uart2wb/lm32/uart2wb.c | 53 ----- miscope/{com => host}/__init__.py | 0 miscope/host/cpuif.py | 11 + miscope/host/drivers.py | 63 ++++++ miscope/host/regs.py | 48 +++++ miscope/{std => host}/truthtable.py | 0 miscope/host/uart2wishbone.py | 78 +++++++ miscope/{std => host}/vcd.py | 0 miscope/mila.py | 2 +- miscope/{std/__init__.py => std.py} | 0 miscope/std/cif.py | 94 -------- miscope/std/misc.py | 89 -------- miscope/uart2wishbone.py | 297 ++++++++++++++++++++++++++ setup.py | 2 +- sim/cpuif.py | 11 + sim/tb_recorder_csr.py | 89 ++++---- sim/tb_rle.py | 20 +- sim/tb_trigger_csr.py | 90 ++++---- 32 files changed, 601 insertions(+), 1158 deletions(-) delete mode 100644 doc/.keep_me delete mode 100644 examples/de0_nano/Makefile delete mode 100644 examples/de0_nano/client/test_miio.py delete mode 100644 examples/de0_nano/client/test_mila.py delete mode 100644 examples/de0_nano/make.py delete mode 100644 examples/de0_nano/timings.py delete mode 100644 examples/de0_nano/top.py delete mode 100644 miscope/com/uart2csr/__init__.py delete mode 100644 miscope/com/uart2csr/host/__init__.py delete mode 100644 miscope/com/uart2csr/host/uart2csr.py delete mode 100644 miscope/com/uart2csr/uart.py delete mode 100644 miscope/com/uart2wb/__init__.py delete mode 100644 miscope/com/uart2wb/host/__init__.py delete mode 100644 miscope/com/uart2wb/host/uart2wb.py delete mode 100644 miscope/com/uart2wb/lm32/uart2wb.c rename miscope/{com => host}/__init__.py (100%) create mode 100644 miscope/host/cpuif.py create mode 100644 miscope/host/drivers.py create mode 100644 miscope/host/regs.py rename miscope/{std => host}/truthtable.py (100%) create mode 100644 miscope/host/uart2wishbone.py rename miscope/{std => host}/vcd.py (100%) rename miscope/{std/__init__.py => std.py} (100%) delete mode 100644 miscope/std/cif.py delete mode 100644 miscope/std/misc.py create mode 100644 miscope/uart2wishbone.py create mode 100644 sim/cpuif.py diff --git a/doc/.keep_me b/doc/.keep_me deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/de0_nano/Makefile b/examples/de0_nano/Makefile deleted file mode 100644 index 53b90086..00000000 --- a/examples/de0_nano/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -all: build/soc-de0nano.sta - -build/soc-de0nano.sta: - ./make.py - -load: - cd build && quartus_pgm -m jtag -c USB-Blaster[USB-0] -o "p;soc-de0nano.sof" - -clean: - rm -rf build/* - -.PHONY: load clean diff --git a/examples/de0_nano/client/test_miio.py b/examples/de0_nano/client/test_miio.py deleted file mode 100644 index 529f86ac..00000000 --- a/examples/de0_nano/client/test_miio.py +++ /dev/null @@ -1,57 +0,0 @@ -from miscope import miio -from miscope.com.uart2csr.host.uart2csr import * - -from csr import * - -#============================================================================== -# P A R A M E T E R S -#============================================================================== - -uart = Uart2Csr(3, 115200) - -class MiIoCtrl(): - def __init__(self, bus): - self.bus = bus - - def write(self, value): - miio_o_write(self.bus, value) - - def read(self): - return miio_i_read(self.bus) - -miio = MiIoCtrl(uart) - -def led_anim0(): - for i in range(10): - miio.write(0xA5) - time.sleep(0.1) - miio.write(0x5A) - time.sleep(0.1) - -def led_anim1(): - for j in range(4): - #Led << - ledData = 1 - for i in range(8): - miio.write(ledData) - time.sleep(i*i*0.0020) - ledData = (ledData<<1) - #Led >> - ledData = 128 - for i in range(8): - miio.write(ledData) - time.sleep(i*i*0.0020) - ledData = (ledData>>1) - -#============================================================================== -# T E S T M I I O -#============================================================================== - -print("- Led Animation...") -led_anim0() -time.sleep(1) -led_anim1() -time.sleep(1) - -print("- Read Switch: ",end=' ') -print("%02X" %miio.read()) diff --git a/examples/de0_nano/client/test_mila.py b/examples/de0_nano/client/test_mila.py deleted file mode 100644 index ceeedb30..00000000 --- a/examples/de0_nano/client/test_mila.py +++ /dev/null @@ -1,99 +0,0 @@ -from miscope import mila -from miscope.std.truthtable import * -from miscope.std.vcd import * -from miscope.com.uart2csr.host.uart2csr import * -from csr import * - -#============================================================================== -# P A R A M E T E R S -#============================================================================== - -uart = Uart2Csr(3, 115200) - -class MiLaCtrl(): - def __init__(self, bus): - self.bus = bus - - def prog_term(self, trigger, mask): - mila_trigger_port0_trig_write(self.bus, trigger) - mila_trigger_port0_mask_write(self.bus, mask) - - def prog_sum(self, datas): - for adr, dat in enumerate(datas): - mila_trigger_sum_prog_adr_write(self.bus, adr) - mila_trigger_sum_prog_dat_write(self.bus, dat) - mila_trigger_sum_prog_we_write(self.bus, 1) - - def enable_rle(self): - mila_rle_enable_write(self.bus, 1) - - def disable_rle(self): - mila_rle_enable_write(self.bus, 0) - - def is_done(self): - return mila_recorder_done_read(self.bus) - - def trigger(self, offset, length): - mila_recorder_offset_write(self.bus, offset) - mila_recorder_length_write(self.bus, length) - mila_recorder_trigger_write(self.bus, 1) - - def read(self): - r = [] - empty = mila_recorder_read_empty_read(self.bus) - while(not empty): - r.append(mila_recorder_read_dat_read(self.bus)) - empty = mila_recorder_read_empty_read(self.bus) - mila_recorder_read_en_write(self.bus, 1) - return r - -# Mila Param -trig_w = 16 -dat_w = 16 -rec_length = 512 -rec_offset = 0 -rle = True - -#============================================================================== -# T E S T M I L A -#============================================================================== -dat_vcd = VcdDat(dat_w) - -mila = MiLaCtrl(uart) - -def capture(): - global dat_vcd - sum_tt = gen_truth_table("term") - mila.prog_sum(sum_tt) - mila.trigger(rec_offset, rec_length) - print("-Recorder [Triggered]") - print("-Waiting Trigger...", end=' ') - while(not mila.is_done()): - time.sleep(0.1) - print("[Done]") - - print("-Receiving Data...", end=' ') - sys.stdout.flush() - dat_vcd += mila.read() - print("[Done]") - -print("Capturing ...") -print("----------------------") -if rle: - mila.enable_rle() -mila.prog_term(0x0000, 0xFFFF) -capture() - -mila_layout = [ - ("freqgen", 1), - ("event_rising", 1), - ("event_falling", 1), - ("cnt", 8), - ] - -if rle: - dat_vcd = dat_vcd.decode_rle() - -myvcd = Vcd() -myvcd.add_from_layout(mila_layout, dat_vcd) -myvcd.write("test_mila.vcd") \ No newline at end of file diff --git a/examples/de0_nano/make.py b/examples/de0_nano/make.py deleted file mode 100644 index e0e5c010..00000000 --- a/examples/de0_nano/make.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 - -import argparse, os, subprocess, struct, shutil - -from mibuild.tools import write_to_file -import mibuild.platforms.de0nano as de0nano - -from miscope.std import cif - -import top - -def build(build_bitstream, build_header): - platform = de0nano.Platform() - soc = top.SoC(platform) - - platform.add_platform_command(""" -set_global_assignment -name FAMILY "Cyclone IV E" -set_global_assignment -name TOP_LEVEL_ENTITY "top" -set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005 -""") - - if build_bitstream: - build_name = "soc-de0nano" - platform.build(soc, build_name=build_name) - else: - soc.finalize() - if build_header: - - csr_py_header = cif.get_py_csr_header(soc.csr_base, soc.csrbankarray) - write_to_file(os.path.join("client", "csr.py"), csr_py_header) - - -def main(): - parser = argparse.ArgumentParser(description="miscope") - parser.add_argument("-B", "--no-bitstream", default=False, action="store_true", help="do not build bitstream file") - parser.add_argument("-H", "--no-header", default=False, action="store_true", help="do not build C header file with CSR defs") - args = parser.parse_args() - - build(not args.no_bitstream, not args.no_header) - -if __name__ == "__main__": - main() diff --git a/examples/de0_nano/timings.py b/examples/de0_nano/timings.py deleted file mode 100644 index 56e3afc2..00000000 --- a/examples/de0_nano/timings.py +++ /dev/null @@ -1,29 +0,0 @@ -from math import ceil - -Hz = 1 -KHz = 10**3 -MHz = 10**6 -GHz = 10**9 - -s = 1 -ms = 1/KHz -us = 1/MHz -ns = 1/GHz - -class t2n: - def __init__(self, clk_period_ns): - self.clk_period_ns = clk_period_ns - self.clk_period_us = clk_period_ns*(MHz/GHz) - self.clk_period_ms = clk_period_ns*(KHz/GHz) - def ns(self,t,margin=True): - if margin: - t += self.clk_period_ns/2 - return ceil(t/self.clk_period_ns) - def us(self,t,margin=True): - if margin: - t += self.clk_period_us/2 - return ceil(t/self.clk_period_us) - def ms(self,t,margin=True): - if margin: - t += self.clk_period_ms/2 - return ceil(t/self.clk_period_ms) \ No newline at end of file diff --git a/examples/de0_nano/top.py b/examples/de0_nano/top.py deleted file mode 100644 index 617399ef..00000000 --- a/examples/de0_nano/top.py +++ /dev/null @@ -1,106 +0,0 @@ -################################################################################ -# _____ _ ____ _ _ _ _ -# | __|___ |_|___ _ _ | \|_|___|_| |_ ___| | -# | __| | | | . | | | | | | | . | | _| .'| | -# |_____|_|_|_| |___|_ | |____/|_|_ |_|_| |__,|_| -# |___| |___| |___| -# -# Copyright 2013 / Florent Kermarrec / florent@enjoy-digital.fr -# -# miscope example on De0 Nano -# -------------------------------- -################################################################################ - -#============================================================================== -# I M P O R T -#============================================================================== -from migen.fhdl.std import * -from migen.bus import csr -from migen.bank import csrgen - -from miscope.std.misc import * - -from miscope.trigger import Term -from miscope.miio import MiIo -from miscope.mila import MiLa - -from miscope.com import uart2csr - -from timings import * - -#============================================================================== -# P A R A M E T E R S -#============================================================================== - -# Timings Param -clk_freq = 50*MHz - -# Mila Param -mila_width = 16 -mila_depth = 4096 - -#============================================================================== -# M I S C O P E E X A M P L E -#============================================================================== -class SoC(Module): - csr_base = 0xe0000000 - csr_map = { - "miio": 1, - "mila": 2, - } - - def __init__(self, platform): - # MiIo - self.submodules.miio = MiIo(8) - - # MiLa - term = Term(mila_width) - self.submodules.mila = MiLa(mila_width, mila_depth, [term], rle=True) - - # Uart2Csr - self.submodules.uart2csr = uart2csr.Uart2Csr(platform.request("serial"), clk_freq, 115200) - - # Csr Interconnect - self.submodules.csrbankarray = csrgen.BankArray(self, - lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override]) - self.submodules.csrcon = csr.Interconnect(self.uart2csr.csr, self.csrbankarray.get_buses()) - - # Led - self.led = Cat(*[platform.request("user_led", i) for i in range(8)]) - - # Misc - self.cnt = Signal(16) - self.submodules.freqgen = FreqGen(clk_freq, 500*KHz) - self.submodules.eventgen_rising = EventGen(RISING_EDGE, clk_freq, 100*ns) - self.submodules.eventgen_falling = EventGen(FALLING_EDGE, clk_freq, 100*ns) - self.comb += [ - self.eventgen_rising.i.eq(self.freqgen.o), - self.eventgen_falling.i.eq(self.freqgen.o) - ] - - - ### - - # - # Miio - # - - # Output - self.comb += self.led.eq(self.miio.o) - - # Input - self.comb += self.miio.i.eq(self.miio.o) - - # - # Mila - # - self.comb +=[ - self.mila.sink.stb.eq(1), - self.mila.sink.dat.eq(Cat( - self.freqgen.o, - self.eventgen_rising.o, - self.eventgen_falling.o, - self.cnt[8:12]) - ) - ] - self.sync += self.cnt.eq(self.cnt+1) diff --git a/miscope/com/uart2csr/__init__.py b/miscope/com/uart2csr/__init__.py deleted file mode 100644 index 3f97ad3e..00000000 --- a/miscope/com/uart2csr/__init__.py +++ /dev/null @@ -1,180 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.module import * -from migen.bus import csr -from migen.genlib.fsm import FSM, NextState - -from miscope.com.uart2csr.uart import * - -WRITE_CMD = 0x01 -READ_CMD = 0x02 -CLOSE_CMD = 0x03 - -class Uart2Csr(Module): - def __init__(self, pads, clk_freq, baud): - - # Csr interface - self.csr = csr.Interface() - - ### - - self.submodules.uart = UART(clk_freq, baud) - uart = self.uart - - # - # In/Out - # - self.comb +=[ - uart.rx.eq(pads.rx), - pads.tx.eq(uart.tx) - ] - - cmd = Signal(8) - cnt = Signal(3) - sr = Signal(32) - burst_cnt = Signal(8) - addr = Signal(32) - data = Signal(8) - - # FSM - self.submodules.fsm = FSM(reset_state="IDLE") - - fsm = self.fsm - - # - # Global - # - self.sync +=[ - If(fsm.ongoing("IDLE"), cnt.eq(0) - ).Elif(uart.rx_ev, cnt.eq(cnt + 1)), - - If(uart.rx_ev, sr.eq(Cat(uart.rx_dat, sr[0:24]))) - ] - - # State done signals - get_bl_done = Signal() - get_addr_done = Signal() - get_addr_done_d = Signal() - get_data_done = Signal() - send_data_done = Signal() - - # - # Idle - # - fsm.act("IDLE", - If(uart.rx_ev & ((uart.rx_dat == WRITE_CMD) | (uart.rx_dat == READ_CMD)), - NextState("GET_BL") - ) - ) - - self.sync += If(fsm.ongoing("IDLE") & uart.rx_ev, cmd.eq(uart.rx_dat)) - - # - # Get burst length - # - fsm.act("GET_BL", - If(get_bl_done, - NextState("GET_ADDR") - ) - ) - - self.comb += get_bl_done.eq(uart.rx_ev & fsm.ongoing("GET_BL")) - - self.sync += If(get_bl_done, burst_cnt.eq(uart.rx_dat)) - - # - # Get address - # - fsm.act("GET_ADDR", - If(get_addr_done & (cmd == WRITE_CMD), - NextState("GET_DATA") - ).Elif(get_addr_done & (cmd == READ_CMD), - NextState("READ_CSR0") - ) - ) - - self.comb += get_addr_done.eq(uart.rx_ev & (cnt == 4) & fsm.ongoing("GET_ADDR")) - self.sync += get_addr_done_d.eq(get_addr_done) - - self.sync += [ - If(get_addr_done_d, - addr.eq(sr) - ).Elif(fsm.leaving("WRITE_CSR") | send_data_done, - addr.eq(addr + 1) - ) - ] - - # - # Get data - # - fsm.act("GET_DATA", - If(get_data_done, - NextState("WRITE_CSR") - ) - ) - - self.comb += get_data_done.eq(uart.rx_ev & fsm.ongoing("GET_DATA")) - self.sync += [ - If(get_data_done, - burst_cnt.eq(burst_cnt-1), - data.eq(uart.rx_dat) - ) - ] - - # - # Write Csr - # - fsm.act("WRITE_CSR", - If((burst_cnt==0), - NextState("IDLE") - ).Else(NextState("GET_DATA")) - ) - - - # - # Read Csr0 - # - fsm.act("READ_CSR0", - NextState("READ_CSR1") - ) - - self.sync += If(fsm.entering("READ_CSR0"), burst_cnt.eq(burst_cnt-1)) - - # - # Read Csr1 - # - fsm.act("READ_CSR1", - NextState("SEND_DATA") - ) - - - # - # Send Data - # - fsm.act("SEND_DATA", - If(send_data_done & (burst_cnt==0), - NextState("IDLE") - ).Elif(send_data_done, - NextState("READ_CSR0") - ) - ) - - self.comb += send_data_done.eq(fsm.ongoing("SEND_DATA") & uart.tx_ev) - - self.sync += [ - uart.tx_dat.eq(self.csr.dat_r), - uart.tx_we.eq(fsm.entering("SEND_DATA")), - ] - - - # - # Csr access - # - self.comb += self.csr.adr.eq(addr) - self.sync +=[ - self.csr.dat_w.eq(data), - If(fsm.ongoing("WRITE_CSR"), - self.csr.we.eq(1) - ).Else( - self.csr.we.eq(0) - ) - ] \ No newline at end of file diff --git a/miscope/com/uart2csr/host/__init__.py b/miscope/com/uart2csr/host/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/miscope/com/uart2csr/host/uart2csr.py b/miscope/com/uart2csr/host/uart2csr.py deleted file mode 100644 index c1ce7d08..00000000 --- a/miscope/com/uart2csr/host/uart2csr.py +++ /dev/null @@ -1,91 +0,0 @@ -import string -import time -import serial -from struct import * -import time -from migen.fhdl.structure import * - -WRITE_CMD = 0x01 -READ_CMD = 0x02 -CLOSE_CMD = 0x03 - -def write_b(uart, data): - uart.write(pack('B',data)) - -class Uart2Csr: - def __init__(self, port, baudrate, debug=False): - self.port = port - self.baudrate = baudrate - self.debug = debug - self.uart = serial.Serial(port, baudrate, timeout=0.25) - - def open(self): - self.uart.close() - self.uart.open() - - def close(self): - self.uart.close() - - def read_csr(self, addr, burst_length=1): - write_b(self.uart, READ_CMD) - write_b(self.uart, burst_length) - addr = addr//4 - write_b(self.uart, (addr & 0xff000000) >> 24) - write_b(self.uart, (addr & 0x00ff0000) >> 16) - write_b(self.uart, (addr & 0x0000ff00) >> 8) - write_b(self.uart, (addr & 0x000000ff)) - values = [] - for i in range(burst_length): - read = self.uart.read(1) - val = int(read[0]) - if self.debug: - print("RD %02X @ %08X" %(val, addr + 4*i)) - values.append(val) - if burst_length == 1: - return values[0] - else: - return values - - def read_n(self, addr, n, endianess = "LE"): - r = 0 - words = int(2**bits_for(n-1)/8) - for i in range(words): - if endianess == "BE": - r += self.read(addr+i)<<(8*i) - elif endianess == "LE": - r += self.read(addr+words-1-i)<<(8*i) - if self.debug: - print("RD @ %04X" %addr) - return r - - def write_csr(self, addr, data): - if isinstance(data, list): - burst_length = len(data) - else: - burst_length = 1 - write_b(self.uart, WRITE_CMD) - write_b(self.uart, burst_length) - addr = addr//4 - self.uart.write([(addr & 0xff000000) >> 24, - (addr & 0x00ff0000) >> 16, - (addr & 0x0000ff00) >> 8, - (addr & 0x000000ff)]) - if isinstance(data, list): - for i in range(len(data)): - write_b(self.uart, data[i]) - if self.debug: - print("WR %02X @ %08X" %(data[i], addr + 4*i)) - else: - write_b(self.uart, data) - if self.debug: - print("WR %02X @ %08X" %(data, addr)) - - def write_n(self, addr, data, n, endianess = "LE"): - words = int(2**bits_for(n-1)/8) - for i in range(words): - if endianess == "BE": - self.write(addr+i, (data>>(8*i)) & 0xFF) - elif endianess == "LE": - self.write(addr+words-1-i, (data>>(8*i)) & 0xFF) - if self.debug: - print("WR %08X @ %04X" %(data, addr)) \ No newline at end of file diff --git a/miscope/com/uart2csr/uart.py b/miscope/com/uart2csr/uart.py deleted file mode 100644 index fe2e9e06..00000000 --- a/miscope/com/uart2csr/uart.py +++ /dev/null @@ -1,107 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.module import Module -from migen.genlib.cdc import MultiReg -from migen.bank.description import * -from migen.bank.eventmanager import * - -class UART(Module): - def __init__(self, clk_freq, baud=115200): - - self.rx_ev = Signal() - self.rx_dat = Signal(8) - - self.tx_we = Signal() - self.tx_ev = Signal() - self.tx_dat = Signal(8) - - self.divisor = Signal(16, reset=int(clk_freq/baud/16)) - - self.tx = Signal(reset=1) - self.rx = Signal() - - - ### - - enable16 = Signal() - enable16_counter = Signal(16) - self.comb += enable16.eq(enable16_counter == 0) - self.sync += [ - enable16_counter.eq(enable16_counter - 1), - If(enable16, - enable16_counter.eq(self.divisor - 1)) - ] - - # TX - tx_reg = Signal(8) - tx_bitcount = Signal(4) - tx_count16 = Signal(4) - tx_done = self.tx_ev - tx_busy = Signal() - self.sync += [ - tx_done.eq(0), - If(self.tx_we, - tx_reg.eq(self.tx_dat), - tx_bitcount.eq(0), - tx_count16.eq(1), - tx_busy.eq(1), - self.tx.eq(0) - ).Elif(enable16 & tx_busy, - tx_count16.eq(tx_count16 + 1), - If(tx_count16 == 0, - tx_bitcount.eq(tx_bitcount + 1), - If(tx_bitcount == 8, - self.tx.eq(1) - ).Elif(tx_bitcount == 9, - self.tx.eq(1), - tx_busy.eq(0), - tx_done.eq(1) - ).Else( - self.tx.eq(tx_reg[0]), - tx_reg.eq(Cat(tx_reg[1:], 0)) - ) - ) - ) - ] - - # RX - rx = Signal() - self.specials += MultiReg(self.rx, rx, "sys") - rx_r = Signal() - rx_reg = Signal(8) - rx_bitcount = Signal(4) - rx_count16 = Signal(4) - rx_busy = Signal() - rx_done = self.rx_ev - rx_data = self.rx_dat - self.sync += [ - rx_done.eq(0), - If(enable16, - rx_r.eq(rx), - If(~rx_busy, - If(~rx & rx_r, # look for start bit - rx_busy.eq(1), - rx_count16.eq(7), - rx_bitcount.eq(0) - ) - ).Else( - rx_count16.eq(rx_count16 + 1), - If(rx_count16 == 0, - rx_bitcount.eq(rx_bitcount + 1), - - If(rx_bitcount == 0, - If(rx, # verify start bit - rx_busy.eq(0) - ) - ).Elif(rx_bitcount == 9, - rx_busy.eq(0), - If(rx, # verify stop bit - rx_data.eq(rx_reg), - rx_done.eq(1) - ) - ).Else( - rx_reg.eq(Cat(rx_reg[1:], rx)) - ) - ) - ) - ) - ] diff --git a/miscope/com/uart2wb/__init__.py b/miscope/com/uart2wb/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/miscope/com/uart2wb/host/__init__.py b/miscope/com/uart2wb/host/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/miscope/com/uart2wb/host/uart2wb.py b/miscope/com/uart2wb/host/uart2wb.py deleted file mode 100644 index 2d86cc00..00000000 --- a/miscope/com/uart2wb/host/uart2wb.py +++ /dev/null @@ -1,89 +0,0 @@ -import string -import time -import serial -from struct import * -import time - -WRITE_CMD = 0x01 -READ_CMD = 0x02 -CLOSE_CMD = 0x03 - -def write_b(uart, data): - uart.write(pack('B',data)) - -class Uart2Wb: - def __init__(self, port, baudrate, debug = False): - self.port = port - self.baudrate = baudrate - self.debug = debug - self.uart = serial.Serial(port, baudrate, timeout=0.25) - - def open(self): - self.uart.write("\nuart2wb\n".encode('ascii')) - self.uart.flush() - time.sleep(0.1) - self.uart.close() - self.uart.open() - - def close(self): - for i in range(16): - write_b(self.uart, CLOSE_CMD) - self.uart.close() - - def read(self, addr, burst_length=1): - write_b(self.uart, READ_CMD) - write_b(self.uart, burst_length) - write_b(self.uart, (addr & 0xff000000) >> 24) - write_b(self.uart, (addr & 0x00ff0000) >> 16) - write_b(self.uart, (addr & 0x0000ff00) >> 8) - write_b(self.uart, (addr & 0x000000ff)) - values = [] - for i in range(burst_length): - read = self.uart.read(4) - val = (int(read[0]) << 24) | (int(read[1]) << 16) | (int(read[2]) << 8) | int(read[3]) - if self.debug: - print("RD %08X @ %08X" %(val, addr + 4*i)) - values.append(val) - if burst_length == 1: - return values[0] - else: - return values - - def read_csr(self, addr, burst_length=1): - values = self.read(addr, burst_length) - if isinstance(values, list): - for i in range(len(values)): - values[i] = values[i]&0xff - else: - values = values & 0xff - return values - - def write(self, addr, data): - if isinstance(data, list): - burst_length = len(data) - else: - burst_length = 1 - write_b(self.uart, WRITE_CMD) - write_b(self.uart, burst_length) - self.uart.write([(addr & 0xff000000) >> 24, - (addr & 0x00ff0000) >> 16, - (addr & 0x0000ff00) >> 8, - (addr & 0x000000ff)]) - if isinstance(data, list): - for i in range(len(data)): - self.uart.write([(data[i] & 0xff000000) >> 24, - (data[i] & 0x00ff0000) >> 16, - (data[i] & 0x0000ff00) >> 8, - (data[i] & 0x000000ff)]) - if self.debug: - print("WR %08X @ %08X" %(elt, addr + 4*i)) - else: - self.uart.write([(data & 0xff000000) >> 24, - (data & 0x00ff0000) >> 16, - (data & 0x0000ff00) >> 8, - (data & 0x000000ff)]) - if self.debug: - print("WR %08X @ %08X" %(data, addr)) - - def write_csr(self, addr, data): - self.write(addr, data) \ No newline at end of file diff --git a/miscope/com/uart2wb/lm32/uart2wb.c b/miscope/com/uart2wb/lm32/uart2wb.c deleted file mode 100644 index dcd9cada..00000000 --- a/miscope/com/uart2wb/lm32/uart2wb.c +++ /dev/null @@ -1,53 +0,0 @@ -// Use this code in your LM32 code to control CSR -// over uart - -#define WRITE_CMD 0x01 -#define READ_CMD 0x02 -#define CLOSE_CMD 0x03 -#define MMPTR(x) (*((volatile unsigned int *)(x))) - -static void uart2wb(void) -{ - unsigned char cmd; - unsigned char burst_length; - unsigned char adr_t[4]; - unsigned int adr; - char data_t[4]; - unsigned int data; - unsigned char i; - unsigned char j; - - while(cmd != CLOSE_CMD) - { - cmd = readchar(); - - if (cmd == WRITE_CMD) - { - burst_length = readchar(); - for(i=0;i<4;i++) adr_t[i] = readchar(); - adr = adr_t[0]<<24 | adr_t[1]<<16 | adr_t[2]<<8 | adr_t[3]; - for(i=0;i>24; - data_t[1] = (data & 0x00ff0000)>>16; - data_t[2] = (data & 0x0000ff00)>>8; - data_t[3] = (data & 0x000000ff); - for(j=0;j<4;j++) putchar(data_t[j]); - } - } - } -} diff --git a/miscope/com/__init__.py b/miscope/host/__init__.py similarity index 100% rename from miscope/com/__init__.py rename to miscope/host/__init__.py diff --git a/miscope/host/cpuif.py b/miscope/host/cpuif.py new file mode 100644 index 00000000..6a0ed40b --- /dev/null +++ b/miscope/host/cpuif.py @@ -0,0 +1,11 @@ +from migen.bank.description import CSRStatus + +def get_csr_csv(csr_base, bank_array): + r = "" + for name, csrs, mapaddr, rmap in bank_array.banks: + reg_base = csr_base + 0x800*mapaddr + for csr in csrs: + nr = (csr.size + 7)//8 + r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, reg_base, nr, "ro" if isinstance(csr, CSRStatus) else "rw") + reg_base += 4*nr + return r diff --git a/miscope/host/drivers.py b/miscope/host/drivers.py new file mode 100644 index 00000000..f44ef39f --- /dev/null +++ b/miscope/host/drivers.py @@ -0,0 +1,63 @@ + +class MiIoDriver(): + def __init__(self, regs, name): + self.regs = regs + self.name = name + self.build_miio() + + def build_miio(self): + for key, value in self.regs.d.items(): + if self.name in key: + key.replace(self.name, "miio") + setattr(self, key, value) + + def write(self, value): + self.miio_o.write(value) + + def read(self): + return self.miio_i.read() + +class MiLaDriver(): + def __init__(self, regs, name): + self.regs = regs + self.name = name + self.build_mila() + + def build_mila(self): + for key, value in self.regs.d.items(): + if self.name in key: + key.replace(self.name, "mila") + setattr(self, key, value) + + def prog_term(self, trigger, mask): + self.mila_trigger_port0_trig.write(trigger) + self.mila_trigger_port0_mask.write(mask) + + def prog_sum(self, datas): + for adr, dat in enumerate(datas): + self.mila_trigger_sum_prog_adr.write(adr) + self.mila_trigger_sum_prog_dat.write(dat) + self.mila_trigger_sum_prog_we.write(1) + + def enable_rle(self): + self.mila_rle_enable.write(1) + + def disable_rle(self): + self.mila_rle_enable.write(0) + + def is_done(self): + return self.mila_recorder_done.read() + + def trigger(self, offset, length): + self.mila_recorder_offset.write(offset) + self.mila_recorder_length.write(length) + self.mila_recorder_trigger.write(1) + + def read(self): + r = [] + empty = self.mila_recorder_read_empty.read() + while(not empty): + r.append(self.mila_recorder_read_dat.read()) + empty = self.mila_recorder_read_empty.read() + self.mila_recorder_read_en.write(1) + return r \ No newline at end of file diff --git a/miscope/host/regs.py b/miscope/host/regs.py new file mode 100644 index 00000000..3b5cdb3b --- /dev/null +++ b/miscope/host/regs.py @@ -0,0 +1,48 @@ +import csv + +class MappedReg: + def __init__(self, readfn, writefn, name, addr, length, mode): + self.readfn = readfn + self.writefn = writefn + self.addr = addr + self.length = length + self.mode = mode + + def read(self): + if self.mode not in ["rw", "ro"]: + raise KeyError(name + "register not readable") + r = 0 + for i in range(self.length): + r |= self.readfn(self.addr + 4*i) + if i != (self.length-1): + r <<= 8 + return r + + def write(self, value): + if self.mode not in ["rw", "wo"]: + raise KeyError(name + "register not writable") + for i in range(self.length): + dat = (value >> ((self.length-1-i)*8)) & 0xff + self.writefn(self.addr + 4*i, dat) + +class MappedRegs: + def __init__(self, d): + self.d = d + + def __getattr__(self, attr): + try: + return self.__dict__['d'][attr] + except KeyError: + pass + + raise KeyError("No such register " + attr) + +def build_map(addrmap, readfn, writefn): + csv_reader = csv.reader(open(addrmap), delimiter=',', quotechar='#') + d = {} + for item in csv_reader: + name, addr, length, mode = item + addr = int(addr.replace("0x", ""), 16) + length = int(length) + d[name] = MappedReg(readfn, writefn, name, addr, length, mode) + return MappedRegs(d) \ No newline at end of file diff --git a/miscope/std/truthtable.py b/miscope/host/truthtable.py similarity index 100% rename from miscope/std/truthtable.py rename to miscope/host/truthtable.py diff --git a/miscope/host/uart2wishbone.py b/miscope/host/uart2wishbone.py new file mode 100644 index 00000000..8cf29ce0 --- /dev/null +++ b/miscope/host/uart2wishbone.py @@ -0,0 +1,78 @@ +import string +import serial +from struct import * +from migen.fhdl.structure import * +from miscope.host.regs import * + +def write_b(uart, data): + uart.write(pack('B',data)) + +class Uart2Wishbone: + WRITE_CMD = 0x01 + READ_CMD = 0x02 + def __init__(self, port, baudrate, addrmap=None, debug=False): + self.port = port + self.baudrate = baudrate + self.debug = debug + self.uart = serial.Serial(port, baudrate, timeout=0.25) + self.regs = build_map(addrmap, self.read, self.write) + + def open(self): + self.uart.flushOutput() + self.uart.close() + self.uart.open() + self.uart.flushInput() + + def close(self): + self.uart.close() + + def read(self, addr, burst_length=1): + self.uart.flushInput() + write_b(self.uart, self.READ_CMD) + write_b(self.uart, burst_length) + addr = addr//4 + write_b(self.uart, (addr & 0xff000000) >> 24) + write_b(self.uart, (addr & 0x00ff0000) >> 16) + write_b(self.uart, (addr & 0x0000ff00) >> 8) + write_b(self.uart, (addr & 0x000000ff)) + values = [] + for i in range(burst_length): + val = 0 + for j in range(4): + val = val << 8 + val |= ord(self.uart.read()) + if self.debug: + print("RD %08X @ %08X" %(val, (addr+i)*4)) + values.append(val) + if burst_length == 1: + return values[0] + else: + return values + + def write(self, addr, data): + if isinstance(data, list): + burst_length = len(data) + else: + burst_length = 1 + write_b(self.uart, self.WRITE_CMD) + write_b(self.uart, burst_length) + addr = addr//4 + write_b(self.uart, (addr & 0xff000000) >> 24) + write_b(self.uart, (addr & 0x00ff0000) >> 16) + write_b(self.uart, (addr & 0x0000ff00) >> 8) + write_b(self.uart, (addr & 0x000000ff)) + if isinstance(data, list): + for i in range(len(data)): + dat = data[i] + for j in range(4): + write_b(self.uart, (dat & 0xff000000) >> 24) + dat = dat << 8 + if self.debug: + print("WR %08X @ %08X" %(data[i], (addr + i)*4)) + else: + dat = data + for j in range(4): + write_b(self.uart, (dat & 0xff000000) >> 24) + dat = dat << 8 + if self.debug: + print("WR %08X @ %08X" %(data, (addr * 4))) diff --git a/miscope/std/vcd.py b/miscope/host/vcd.py similarity index 100% rename from miscope/std/vcd.py rename to miscope/host/vcd.py diff --git a/miscope/mila.py b/miscope/mila.py index 530082b2..656573f0 100644 --- a/miscope/mila.py +++ b/miscope/mila.py @@ -7,7 +7,7 @@ from migen.bank.description import * from miscope.std import * from miscope.trigger import Trigger -from miscope.storage import RunLengthEncoder, Recorder +from miscope.storage import Recorder, RunLengthEncoder class MiLa(Module, AutoCSR): def __init__(self, width, depth, ports, rle=False): diff --git a/miscope/std/__init__.py b/miscope/std.py similarity index 100% rename from miscope/std/__init__.py rename to miscope/std.py diff --git a/miscope/std/cif.py b/miscope/std/cif.py deleted file mode 100644 index 5300908e..00000000 --- a/miscope/std/cif.py +++ /dev/null @@ -1,94 +0,0 @@ -from operator import itemgetter -import re - -from migen.fhdl.std import * -from migen.bank.description import CSRStatus - -def get_macros(filename): - f = open(filename, "r") - r = {} - for line in f: - match = re.match("\w*#define\s+(\w+)\s+(.*)", line, re.IGNORECASE) - if match: - r[match.group(1)] = match.group(2) - return r - -def _get_rw_functions(reg_name, reg_base, size, read_only): - r = "" - if size > 8: - raise NotImplementedError("Register too large") - elif size > 4: - ctype = "unsigned long long int" - elif size > 2: - ctype = "unsigned int" - elif size > 1: - ctype = "unsigned short int" - else: - ctype = "unsigned char" - - r += "static inline "+ctype+" "+reg_name+"_read(void) {\n" - if size > 1: - r += "\t"+ctype+" r = MMPTR("+hex(reg_base)+");\n" - for byte in range(1, size): - r += "\tr <<= 8;\n\tr |= MMPTR("+hex(reg_base+4*byte)+");\n" - r += "\treturn r;\n}\n" - else: - r += "\treturn MMPTR("+hex(reg_base)+");\n}\n" - - if not read_only: - r += "static inline void "+reg_name+"_write("+ctype+" value) {\n" - for byte in range(size): - shift = (size-byte-1)*8 - if shift: - value_shifted = "value >> "+str(shift) - else: - value_shifted = "value" - r += "\tMMPTR("+hex(reg_base+4*byte)+") = "+value_shifted+";\n" - r += "}\n" - return r - -def get_csr_header(csr_base, bank_array): - r = "#ifndef __HW_CSR_H\n#define __HW_CSR_H\n#include \n" - for name, csrs, mapaddr, rmap in bank_array.banks: - r += "\n/* "+name+" */\n" - reg_base = csr_base + 0x800*mapaddr - r += "#define "+name.upper()+"_BASE "+hex(reg_base)+"\n" - for csr in csrs: - nr = (csr.size + 7)//8 - r += _get_rw_functions(name + "_" + csr.name, reg_base, nr, isinstance(csr, CSRStatus)) - reg_base += 4*nr - r += "\n#endif\n" - return r - -def _get_py_rw_functions(reg_name, reg_base, size): - r = "" - - r += "def "+reg_name+"_read(bus):\n" - r += "\tr = bus.read_csr("+hex(reg_base)+")\n" - for byte in range(1, size): - r += "\tr <<= 8\n\tr |= bus.read_csr("+hex(reg_base+4*byte)+")\n" - r += "\treturn r\n\n" - - - r += "def "+reg_name+"_write(bus, value):\n" - for byte in range(size): - shift = (size-byte-1)*8 - if shift: - value_shifted = "value >> "+str(shift) - else: - value_shifted = "value" - r += "\tbus.write_csr("+hex(reg_base+4*byte)+", ("+value_shifted+")&0xff)\n" - r += "\n" - return r - -def get_py_csr_header(csr_base, bank_array): - r = "" - for name, csrs, mapaddr, rmap in bank_array.banks: - r += "\n# "+name+"\n" - reg_base = csr_base + 0x800*mapaddr - r += name.upper()+"_BASE ="+hex(reg_base)+"\n" - for csr in csrs: - nr = (csr.size + 7)//8 - r += _get_py_rw_functions(name + "_" + csr.name, reg_base, nr) - reg_base += 4*nr - return r \ No newline at end of file diff --git a/miscope/std/misc.py b/miscope/std/misc.py deleted file mode 100644 index 57abac81..00000000 --- a/miscope/std/misc.py +++ /dev/null @@ -1,89 +0,0 @@ -from migen.fhdl.std import * - -def dec2bin(d, nb=0): - if d=="x": - return "x"*nb - elif d==0: - b="0" - else: - b="" - while d!=0: - b="01"[d&1]+b - d=d>>1 - return b.zfill(nb) - -class RisingEdge(Module): - def __init__(self): - self.i = Signal() - self.o = Signal() - #### - i_d = Signal() - self.sync += i_d.eq(self.i) - self.comb += self.o.eq(self.i & ~i_d) - -class FallingEdge(Module): - def __init__(self): - self.i = Signal() - self.o = Signal() - #### - i_d = Signal() - self.sync += i_d.eq(self.i) - self.comb += self.o.eq(~self.i & i_d) - -class FreqGen(Module): - def __init__(self, clk_freq, freq): - cnt_max = int(clk_freq/freq/2) - self.o = Signal() - #### - cnt = Signal(max=cnt_max) - self.sync += [ - If(cnt >= cnt_max, - cnt.eq(0), - self.o.eq(~self.o) - ).Else( - cnt.eq(cnt+1) - ) - ] - -RISING_EDGE = 1 -FALLING_EDGE = 0 - -class EventGen(Module): - def __init__(self, level=RISING_EDGE, clk_freq=0, length=1): - cnt_max = int(length*clk_freq) - self.o = Signal() - ### - cnt = Signal(max=cnt_max) - - if level == RISING_EDGE: - self.submodules.edge_detect = RisingEdge() - elif level == FALLING_EDGE: - self.submodules.edge_detect = FallingEdge() - - self.i = self.edge_detect.i - - self.sync += [ - If(self.edge_detect.o == 1, - cnt.eq(0), - self.o.eq(1) - ).Elif(cnt >= cnt_max, - self.o.eq(0) - ).Else( - cnt.eq(cnt+1) - ), - ] - -class PwmGen(Module): - def __init__(self, width): - self.ratio = Signal(width) - self.o = Signal() - ### - cnt = Signal(width) - self.sync += [ - If(cnt == 0, - self.o.eq(1) - ).Elif(cnt >= self.ratio, - self.o.eq(0) - ), - cnt.eq(cnt+1) - ] \ No newline at end of file diff --git a/miscope/uart2wishbone.py b/miscope/uart2wishbone.py new file mode 100644 index 00000000..4fce7738 --- /dev/null +++ b/miscope/uart2wishbone.py @@ -0,0 +1,297 @@ +from migen.fhdl.structure import * +from migen.fhdl.module import * +from migen.genlib.record import * +from migen.genlib.cdc import MultiReg +from migen.genlib.fsm import FSM, NextState +from migen.genlib.misc import split, displacer, chooser +from migen.bank.description import * +from migen.bus import wishbone + + +# Todo +# ---- +# - implement timeout in fsm to prevent deadlocks + +def rec_rx(): + layout = [ + ("stb", 1, DIR_M_TO_S), + ("dat", 8, DIR_M_TO_S) + ] + return Record(layout) + +def rec_tx(): + layout = [ + ("stb", 1, DIR_M_TO_S), + ("ack", 1, DIR_S_TO_M), + ("dat", 8, DIR_M_TO_S) + ] + return Record(layout) + +class UART(Module): + def __init__(self, pads, clk_freq, baud=115200): + + self.rx = rec_rx() + self.tx = rec_tx() + + self.divisor = Signal(16, reset=int(clk_freq/baud/16)) + + pads.tx.reset = 1 + + ### + + enable16 = Signal() + enable16_counter = Signal(16) + self.comb += enable16.eq(enable16_counter == 0) + self.sync += [ + enable16_counter.eq(enable16_counter - 1), + If(enable16, + enable16_counter.eq(self.divisor - 1)) + ] + + # TX + tx_reg = Signal(8) + tx_bitcount = Signal(4) + tx_count16 = Signal(4) + tx_done = self.tx.ack + tx_busy = Signal() + tx_stb_d = Signal() + self.sync += [ + tx_stb_d.eq(self.tx.stb & ~tx_done), + tx_done.eq(0), + If(self.tx.stb & ~tx_stb_d, + tx_reg.eq(self.tx.dat), + tx_bitcount.eq(0), + tx_count16.eq(1), + tx_busy.eq(1), + pads.tx.eq(0) + ).Elif(enable16 & tx_busy, + tx_count16.eq(tx_count16 + 1), + If(tx_count16 == 0, + tx_bitcount.eq(tx_bitcount + 1), + If(tx_bitcount == 8, + pads.tx.eq(1) + ).Elif(tx_bitcount == 9, + pads.tx.eq(1), + tx_busy.eq(0), + tx_done.eq(1) + ).Else( + pads.tx.eq(tx_reg[0]), + tx_reg.eq(Cat(tx_reg[1:], 0)) + ) + ) + ) + ] + + # RX + rx = Signal() + self.specials += MultiReg(pads.rx, rx, "sys") + rx_r = Signal() + rx_reg = Signal(8) + rx_bitcount = Signal(4) + rx_count16 = Signal(4) + rx_busy = Signal() + rx_done = self.rx.stb + rx_data = self.rx.dat + self.sync += [ + rx_done.eq(0), + If(enable16, + rx_r.eq(rx), + If(~rx_busy, + If(~rx & rx_r, # look for start bit + rx_busy.eq(1), + rx_count16.eq(7), + rx_bitcount.eq(0) + ) + ).Else( + rx_count16.eq(rx_count16 + 1), + If(rx_count16 == 0, + rx_bitcount.eq(rx_bitcount + 1), + + If(rx_bitcount == 0, + If(rx, # verify start bit + rx_busy.eq(0) + ) + ).Elif(rx_bitcount == 9, + rx_busy.eq(0), + If(rx, # verify stop bit + rx_data.eq(rx_reg), + rx_done.eq(1) + ) + ).Else( + rx_reg.eq(Cat(rx_reg[1:], rx)) + ) + ) + ) + ) + ] + +class Counter(Module): + def __init__(self, width): + self.value = Signal(width) + self.clr = Signal() + self.inc = Signal() + self.sync += [ + If(self.clr, + self.value.eq(0) + ).Elif(self.inc, + self.value.eq(self.value+1) + ) + ] + +class UARTPads: + def __init__(self): + self.rx = Signal() + self.tx = Signal() + +class UARTMux(Module): + def __init__(self, pads, nb): + self.sel = Signal(max=nb) + self.pads = [UARTPads() for i in range(nb)] + + ### + # Route Rx pad to all modules + for i in range(nb): + self.comb += self.pads[i].rx.eq(pads.rx) + + # Route only selected module to Tx pad + pads_tx = [self.pads[i].tx for i in range(nb)] + self.comb += chooser(Cat(pads_tx), self.sel, pads.tx, n=nb) + + +class UART2Wishbone(Module, AutoCSR): + WRITE_CMD = 0x01 + READ_CMD = 0x02 + def __init__(self, pads, clk_freq, baud, share_uart=False): + + # Wishbone interface + self.wishbone = wishbone.Interface() + if share_uart: + self._sel = CSRStorage() + + ### + if share_uart: + self.submodules.uart_mux = UARTMux(pads, 2) + self.submodules.uart = UART(self.uart_mux.pads[1], clk_freq, baud) + self.shared_pads = self.uart_mux.pads[0] + self.comb += self.uart_mux.sel.eq(self._sel.storage) + else: + self.submodules.uart = UART(pads, clk_freq, baud) + + uart = self.uart + + fsm = FSM() + self.submodules += fsm + + word_cnt = Counter(3) + burst_cnt = Counter(8) + self.submodules += word_cnt, burst_cnt + + ### + cmd = Signal(8) + fsm.act("WAIT_CMD", + If(uart.rx.stb, + If( (uart.rx.dat == self.WRITE_CMD) | + (uart.rx.dat == self.READ_CMD), + NextState("RECEIVE_BURST_LENGTH") + ), + word_cnt.clr.eq(1), + burst_cnt.clr.eq(1) + ) + ) + self.sync += If(fsm.ongoing("WAIT_CMD") & uart.rx.stb, cmd.eq(uart.rx.dat)) + + #### + burst_length = Signal(8) + fsm.act("RECEIVE_BURST_LENGTH", + word_cnt.inc.eq(uart.rx.stb), + If(word_cnt.value == 1, + word_cnt.clr.eq(1), + NextState("RECEIVE_ADDRESS") + ) + ) + self.sync += \ + If(fsm.ongoing("RECEIVE_BURST_LENGTH") & uart.rx.stb, burst_length.eq(uart.rx.dat)) + + #### + address = Signal(32) + fsm.act("RECEIVE_ADDRESS", + word_cnt.inc.eq(uart.rx.stb), + If(word_cnt.value == 4, + word_cnt.clr.eq(1), + If(cmd == self.WRITE_CMD, + NextState("RECEIVE_DATA") + ).Elif(cmd == self.READ_CMD, + NextState("READ_DATA") + ) + ) + ) + self.sync += \ + If(fsm.ongoing("RECEIVE_ADDRESS") & uart.rx.stb, + address.eq(Cat(uart.rx.dat, address[0:24])) + ) + + ### + data = Signal(32) + + ### + fsm.act("RECEIVE_DATA", + word_cnt.inc.eq(uart.rx.stb), + If(word_cnt.value == 4, + word_cnt.clr.eq(1), + NextState("WRITE_DATA") + ) + ) + + fsm.act("WRITE_DATA", + self.wishbone.adr.eq(address + burst_cnt.value), + self.wishbone.dat_w.eq(data), + self.wishbone.sel.eq(2**flen(self.wishbone.sel)-1), + self.wishbone.stb.eq(1), + self.wishbone.we.eq(1), + self.wishbone.cyc.eq(1), + If(self.wishbone.ack, + burst_cnt.inc.eq(1), + If(burst_cnt.value == (burst_length-1), + NextState("WAIT_CMD") + ).Else( + word_cnt.clr.eq(1), + NextState("RECEIVE_DATA") + ) + ) + ) + + ### + fsm.act("READ_DATA", + self.wishbone.adr.eq(address + burst_cnt.value), + self.wishbone.sel.eq(2**flen(self.wishbone.sel)-1), + self.wishbone.stb.eq(1), + self.wishbone.we.eq(0), + self.wishbone.cyc.eq(1), + If(self.wishbone.stb & self.wishbone.ack, + word_cnt.clr.eq(1), + NextState("SEND_DATA") + ) + ) + + fsm.act("SEND_DATA", + word_cnt.inc.eq(uart.tx.ack), + If(word_cnt.value == 4, + burst_cnt.inc.eq(1), + If(burst_cnt.value == (burst_length-1), + NextState("WAIT_CMD") + ).Else( + NextState("READ_DATA") + ) + ), + uart.tx.stb.eq(1), + chooser(data, word_cnt.value, uart.tx.dat, n=4, reverse=True) + ) + + ### + self.sync += \ + If(fsm.ongoing("RECEIVE_DATA") & uart.rx.stb, + data.eq(Cat(uart.rx.dat, data[0:24])) + ).Elif(fsm.ongoing("READ_DATA") & self.wishbone.stb & self.wishbone.ack, + data.eq(self.wishbone.dat_r) + ) + diff --git a/setup.py b/setup.py index de34491d..740be67b 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ from setuptools import find_packages here = os.path.abspath(os.path.dirname(__file__)) README = open(os.path.join(here, "README")).read() -required_version = (3, 1) +required_version = (3, 3) if sys.version_info < required_version: raise SystemExit("Migscope requires python {0} or greater".format( ".".join(map(str, required_version)))) diff --git a/sim/cpuif.py b/sim/cpuif.py new file mode 100644 index 00000000..6a0ed40b --- /dev/null +++ b/sim/cpuif.py @@ -0,0 +1,11 @@ +from migen.bank.description import CSRStatus + +def get_csr_csv(csr_base, bank_array): + r = "" + for name, csrs, mapaddr, rmap in bank_array.banks: + reg_base = csr_base + 0x800*mapaddr + for csr in csrs: + nr = (csr.size + 7)//8 + r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, reg_base, nr, "ro" if isinstance(csr, CSRStatus) else "rw") + reg_base += 4*nr + return r diff --git a/sim/tb_recorder_csr.py b/sim/tb_recorder_csr.py index c4a98fd4..c17cbb74 100644 --- a/sim/tb_recorder_csr.py +++ b/sim/tb_recorder_csr.py @@ -1,21 +1,17 @@ from migen.fhdl.std import * from migen.fhdl import verilog from migen.bus import csr -from migen.sim.generic import Simulator, TopLevel -from migen.sim.icarus import Runner +from migen.sim.generic import run_simulation from migen.bus.transactions import * -from miscope.std import cif -from miscope.std.truthtable import * +from miscope.std import * from miscope.storage import * from mibuild.tools import write_to_file +from miscope.tools.regs import * +from miscope.tools.truthtable import * -try: - from csr_header import * - print("csr_header imported") -except: - print("csr_header not found") +from cpuif import * class Csr2Trans(): def __init__(self): @@ -38,30 +34,26 @@ dat_rdy = False rec_length = 128 -def csr_configure(): - bus = Csr2Trans() - +def csr_configure(bus, regs): # Length - recorder_length_write(bus, rec_length) + regs.recorder_length.write(rec_length) # Offset - recorder_offset_write(bus, 0) + regs.recorder_offset.write(0) # Trigger - recorder_trigger_write(bus, 1) + regs.recorder_trigger.write(1) return bus.t -def csr_read_data(): - bus = Csr2Trans() - +def csr_read_data(bus, regs): for i in range(rec_length+100): - recorder_read_dat_read(bus) - recorder_read_en_write(bus, 1) + regs.recorder_read_dat.read() + regs.recorder_read_en.write(1) return bus.t -def csr_transactions(): - for t in csr_configure(): +def csr_transactions(bus, regs): + for t in csr_configure(bus, regs): yield t for t in range(100): @@ -73,7 +65,7 @@ def csr_transactions(): for t in range(512): yield None - for t in csr_read_data(): + for t in csr_read_data(bus, regs): yield t for t in range(100): @@ -85,56 +77,57 @@ class TB(Module): csr_map = { "recorder": 1, } - def __init__(self, first_run=False): + def __init__(self, addrmap=None): self.csr_base = 0 - # Csr Master - if not first_run: - self.submodules.master = csr.Initiator(csr_transactions()) - # Recorder self.submodules.recorder = Recorder(32, 1024) # Csr self.submodules.csrbankarray = csrgen.BankArray(self, lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override]) - if not first_run: - self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses()) + + # Csr Master + csr_header = get_csr_csv(self.csr_base, self.csrbankarray) + write_to_file("csr.csv", csr_header) + + bus = Csr2Trans() + regs = build_map(addrmap, bus.read_csr, bus.write_csr) + self.submodules.master = csr.Initiator(csr_transactions(bus, regs)) + + self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses()) # Recorder Data - def recorder_data(self, s): - s.wr(self.recorder.sink.stb, 1) + def recorder_data(self, selfp): + selfp.recorder.dat_sink.stb = 1 if not hasattr(self, "cnt"): self.cnt = 0 self.cnt += 1 - s.wr(self.recorder.sink.payload.d, self.cnt) + selfp.recorder.dat_sink.dat = self.cnt global triggered if triggered: - s.wr(self.recorder.sink.payload.hit, 1) + selfp.recorder.trig_sink.stb = 1 + selfp.recorder.trig_sink.hit = 1 triggered = False else: - s.wr(self.recorder.sink.payload.hit, 0) + selfp.recorder.trig_sink.stb = 0 + selfp.recorder.trig_sink.hit = 0 # Simulation - def end_simulation(self, s): - s.interrupt = self.master.done + def end_simulation(self, selfp): + if self.master.done: + raise StopSimulation - - def do_simulation(self, s): - self.recorder_data(s) - self.end_simulation(s) + def do_simulation(self, selfp): + self.recorder_data(selfp) + self.end_simulation(selfp) def main(): - tb = TB(first_run=True) - csr_py_header = cif.get_py_csr_header(tb.csr_base, tb.csrbankarray) - write_to_file("csr_header.py", csr_py_header) - - tb = TB() - sim = Simulator(tb, TopLevel("tb_recorder_csr.vcd")) - sim.run(2000) + tb = TB(addrmap="csr.csv") + run_simulation(tb, ncycles=2000, vcd_name="tb_recorder_csr.vcd") print("Sim Done") input() diff --git a/sim/tb_rle.py b/sim/tb_rle.py index bd68a1ed..9ce98a46 100644 --- a/sim/tb_rle.py +++ b/sim/tb_rle.py @@ -1,10 +1,7 @@ from migen.fhdl.std import * -from migen.fhdl import verilog -from migen.sim.generic import Simulator, TopLevel -from migen.sim.icarus import Runner - -from miscope.storage import RunLengthEncoder +from migen.sim.generic import run_simulation +from miscope import storage rle_test_seq = iter( [ 0x00AA, @@ -29,20 +26,19 @@ class TB(Module): def __init__(self): # Rle - self.submodules.rle = RunLengthEncoder(16, 32) + self.submodules.rle = storage.RunLengthEncoder(16, 32) - def do_simulation(self, s): - s.wr(self.rle._r_enable.storage, 1) - s.wr(self.rle.sink.stb, 1) + def do_simulation(self, selfp): + selfp.rle._r_enable.storage = 1 + selfp.rle.sink.stb = 1 try: - s.wr(self.rle.sink.dat, next(rle_test_seq)) + selfp.rle.sink.dat = next(rle_test_seq) except: pass def main(): tb = TB() - sim = Simulator(tb, TopLevel("tb_rle.vcd")) - sim.run(2000) + run_simulation(tb, ncycles=8000, vcd_name="tb_rle.vcd") print("Sim Done") input() diff --git a/sim/tb_trigger_csr.py b/sim/tb_trigger_csr.py index f669ac84..28cf7e1b 100644 --- a/sim/tb_trigger_csr.py +++ b/sim/tb_trigger_csr.py @@ -1,21 +1,17 @@ from migen.fhdl.std import * from migen.fhdl import verilog from migen.bus import csr -from migen.sim.generic import Simulator, TopLevel -from migen.sim.icarus import Runner +from migen.sim.generic import run_simulation from migen.bus.transactions import * -from miscope.std import cif -from miscope.std.truthtable import * +from miscope.std import * from miscope.trigger import * from mibuild.tools import write_to_file +from miscope.tools.regs import * +from miscope.tools.truthtable import * -try: - from csr_header import * - print("csr_header imported") -except: - print("csr_header not found") +from cpuif import * class Csr2Trans(): def __init__(self): @@ -27,30 +23,29 @@ class Csr2Trans(): def read_csr(self, adr): self.t.append(TRead(adr//4)) -def csr_prog_mila(): - bus = Csr2Trans() - trigger_port0_mask_write(bus, 0xFFFFFFFF) - trigger_port0_trig_write(bus, 0xDEADBEEF) - trigger_port1_mask_write(bus, 0xFFFFFFFF) - trigger_port1_trig_write(bus, 0xDEADBEEF) - trigger_port1_mask_write(bus, 0xFFFFFFFF) - trigger_port1_mask_write(bus, 0xFFFFFFFF) - trigger_port1_trig_write(bus, 0xDEADBEEF) +def csr_prog_mila(bus, regs): + regs.trigger_port0_mask.write(0xFFFFFFFF) + regs.trigger_port0_trig.write(0xDEADBEEF) + regs.trigger_port1_mask.write(0xFFFFFFFF) + regs.trigger_port1_trig.write(0xDEADBEEF) + regs.trigger_port1_mask.write(0xFFFFFFFF) + regs.trigger_port1_mask.write(0xFFFFFFFF) + regs.trigger_port1_trig.write(0xDEADBEEF) sum_tt = gen_truth_table("i1 & i2 & i3 & i4") sum_trans = [] for i in range(len(sum_tt)): - trigger_sum_prog_adr_write(bus, i) - trigger_sum_prog_dat_write(bus, sum_tt[i]) - trigger_sum_prog_we_write(bus, 1) + regs.trigger_sum_prog_adr.write(i) + regs.trigger_sum_prog_dat.write(sum_tt[i]) + regs.trigger_sum_prog_we.write(1) return bus.t csr_done = False -def csr_transactions(): - for t in csr_prog_mila(): +def csr_transactions(bus, regs): + for t in csr_prog_mila(bus, regs): yield t global csr_done csr_done = True @@ -62,13 +57,9 @@ class TB(Module): csr_map = { "trigger": 1, } - def __init__(self, first_run=False): - - - # Csr Master - if not first_run: - self.submodules.master = csr.Initiator(csr_transactions()) - + def __init__(self, addrmap=None): + self.csr_base = 0 + # Trigger term0 = Term(32) term1 = Term(32) @@ -79,29 +70,32 @@ class TB(Module): # Csr self.submodules.csrbankarray = csrgen.BankArray(self, lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override]) - if not first_run: - self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses()) - + + # Csr Master + csr_header = get_csr_csv(self.csr_base, self.csrbankarray) + write_to_file("csr.csv", csr_header) + + bus = Csr2Trans() + regs = build_map(addrmap, bus.read_csr, bus.write_csr) + self.submodules.master = csr.Initiator(csr_transactions(bus, regs)) + + self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses()) + self.terms = [term0, term1, term2, term3] - def do_simulation(self, s): - for term in self.terms: - s.wr(term.sink.stb, 1) + def do_simulation(self, selfp): + for term in selfp.terms: + term.sink.stb = 1 if csr_done: - s.wr(self.terms[0].sink.payload.d, 0xDEADBEEF) - s.wr(self.terms[1].sink.payload.d ,0xCAFEFADE) - s.wr(self.terms[2].sink.payload.d, 0xDEADBEEF) - s.wr(self.terms[3].sink.payload.d, 0xCAFEFADE) - s.interrupt = self.master.done + selfp.terms[0].sink.dat = 0xDEADBEEF + selfp.terms[1].sink.dat = 0xCAFEFADE + selfp.terms[2].sink.dat = 0xDEADBEEF + selfp.terms[3].sink.dat = 0xCAFEFADE + raise StopSimulation def main(): - tb = TB(first_run=True) - csr_py_header = cif.get_py_csr_header(tb.csr_base, tb.csrbankarray) - write_to_file("csr_header.py", csr_py_header) - - tb = TB() - sim = Simulator(tb, TopLevel("tb_trigger_csr.vcd")) - sim.run(2000) + tb = TB(addrmap="csr.csv") + run_simulation(tb, ncycles=2000, vcd_name="tb_trigger_csr.vcd") print("Sim Done") input() -- 2.30.2