From: Florent Kermarrec Date: Sat, 21 Sep 2013 11:04:07 +0000 (+0200) Subject: refactoring X-Git-Tag: 24jan2021_ls180~2575^2~94 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ce9bff21e9c02e5292d12313c27591730b1350d8;p=litex.git refactoring --- diff --git a/examples/de0_nano/Makefile b/examples/de0_nano/Makefile index 00a53a89..53b90086 100644 --- a/examples/de0_nano/Makefile +++ b/examples/de0_nano/Makefile @@ -1,11 +1,10 @@ -all: build/top.sta +all: build/soc-de0nano.sta -build/top.sta: - ./build.py +build/soc-de0nano.sta: + ./make.py load: - cd build && quartus_pgm -m jtag -c USB-Blaster[USB-0] -o "p;top.sof" - + cd build && quartus_pgm -m jtag -c USB-Blaster[USB-0] -o "p;soc-de0nano.sof" clean: rm -rf build/* diff --git a/examples/de0_nano/build.py b/examples/de0_nano/build.py deleted file mode 100644 index 9fb0a24d..00000000 --- a/examples/de0_nano/build.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 - -import os -from mibuild.platforms import de0nano -import top - -def main(): - platform = de0nano.Platform() - soc = top.SoC(platform) - - - # set extra constraints - 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 -""") - - platform.build_cmdline(soc) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/examples/de0_nano/client/test_miio.py b/examples/de0_nano/client/test_miio.py index 747e48d9..529f86ac 100644 --- a/examples/de0_nano/client/test_miio.py +++ b/examples/de0_nano/client/test_miio.py @@ -1,23 +1,31 @@ from miscope import miio -from miscope.bridges.uart2csr.tools.uart2Csr import * +from miscope.com.uart2csr.host.uart2csr import * + +from csr import * #============================================================================== # P A R A M E T E R S #============================================================================== -csr = Uart2Csr(3,115200) +uart = Uart2Csr(3, 115200) + +class MiIoCtrl(): + def __init__(self, bus): + self.bus = bus + + def write(self, value): + miio_o_write(self.bus, value) -# Csr Addr -MIIO_ADDR = 0x00 + def read(self): + return miio_i_read(self.bus) -# Miscope Configuration -miio = miio.MiIo(MIIO_ADDR, 8, "IO", csr) +miio = MiIoCtrl(uart) def led_anim0(): for i in range(10): - miio.set(0xA5) + miio.write(0xA5) time.sleep(0.1) - miio.set(0x5A) + miio.write(0x5A) time.sleep(0.1) def led_anim1(): @@ -25,18 +33,18 @@ def led_anim1(): #Led << ledData = 1 for i in range(8): - miio.set(ledData) + miio.write(ledData) time.sleep(i*i*0.0020) ledData = (ledData<<1) #Led >> ledData = 128 for i in range(8): - miio.set(ledData) + miio.write(ledData) time.sleep(i*i*0.0020) ledData = (ledData>>1) #============================================================================== -# T E S T M I G I O +# T E S T M I I O #============================================================================== print("- Led Animation...") @@ -46,4 +54,4 @@ led_anim1() time.sleep(1) print("- Read Switch: ",end=' ') -print("%02X" %miio.get()) +print("%02X" %miio.read()) diff --git a/examples/de0_nano/client/test_mila.py b/examples/de0_nano/client/test_mila.py index 89768709..86775388 100644 --- a/examples/de0_nano/client/test_mila.py +++ b/examples/de0_nano/client/test_mila.py @@ -1,61 +1,79 @@ -from miscope import trigger, recorder, miio, mila -from miscope.tools.truthtable import * -from miscope.tools.vcd import * -from miscope.bridges.uart2csr.tools.uart2Csr import * +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 #============================================================================== -# Csr Addr -MILA_ADDR = 0x01 -csr = Uart2Csr(3, 115200, debug=False) +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 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_size = 512 -rec_offset = 32 -enable_rle = True - -# Miscope Configuration -# MiLa -term = trigger.Term(trig_w) -trigger = trigger.Trigger(trig_w, [term]) -recorder = recorder.Recorder(dat_w, rec_size) -mila = mila.MiLa(MILA_ADDR, trigger, recorder, csr) - +rec_length = 512 +rec_offset = 0 #============================================================================== -# T E S T M I G L A +# T E S T M I L A #============================================================================== dat_vcd = VcdDat(dat_w) -def capture(size): +mila = MiLaCtrl(uart) + +def capture(): global dat_vcd sum_tt = gen_truth_table("term") - mila.trigger.sum.set(sum_tt) - mila.recorder.reset() - if enable_rle: - mila.recorder.enable_rle() - recorder.set_size(rec_size) - mila.recorder.set_offset(rec_offset) - mila.recorder.arm() - print("-Recorder [Armed]") + mila.prog_sum(sum_tt) + mila.trigger(rec_offset, rec_length) + print("-Recorder [Triggered]") print("-Waiting Trigger...", end=' ') - while(not mila.recorder.is_done()): + while(not mila.is_done()): time.sleep(0.1) print("[Done]") print("-Receiving Data...", end=' ') sys.stdout.flush() - dat_vcd += mila.recorder.pull(rec_size) + dat_vcd += mila.read() print("[Done]") print("Capturing ...") print("----------------------") -term.set(0x0000, 0xFFFF) -capture(rec_size) +mila.prog_term(0x0000, 0xFFFF) +capture() mila_layout = [ ("freqgen", 1), @@ -64,9 +82,6 @@ mila_layout = [ ("cnt", 8), ] -if enable_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 new file mode 100644 index 00000000..e0e5c010 --- /dev/null +++ b/examples/de0_nano/make.py @@ -0,0 +1,42 @@ +#!/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/misc.py b/examples/de0_nano/misc.py deleted file mode 100644 index 1067a5c4..00000000 --- a/examples/de0_nano/misc.py +++ /dev/null @@ -1,111 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.module import Module - -class RisingEdge(Module): - def __init__(self, i=None, o=None, domain="sys"): - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - #### - i_d = Signal() - sync =[i_d.eq(self.i)] - self.comb +=[self.o.eq(self.i & ~i_d)] - self._fragment += Fragment(sync={domain : sync}) - -class FallingEdge(Module): - def __init__(self, i=None, o=None, domain="sys"): - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - #### - i_d = Signal() - sync =[i_d.eq(self.i)] - self.comb +=[self.o.eq(~self.i & i_d)] - self._fragment += Fragment(sync={domain : sync}) - -class FreqGen(Module): - def __init__(self, clk_freq, freq, o=None): - cnt_max = int(clk_freq/freq/2) - width = bits_for(cnt_max) - - self.o = ifthenelse(o, o, Signal()) - #### - cnt = Signal(width) - 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, i=None, level=1, clk_freq=0, length=1, o=None): - - cnt_max = int(length*clk_freq) - width = bits_for(cnt_max) - - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - ### - cnt = Signal(width) - i_edge = Signal() - - if level == RISING_EDGE: - self.submodules += RisingEdge(self.i, i_edge) - elif level == FALLING_EDGE: - self.submodules += FallingEdge(self.i, i_edge) - - self.sync += [ - If(i_edge == 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, o=None): - self.ratio = Signal(width) - self.o = ifthenelse(o, 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) - ] - -class Cascade(Module): - def __init__(self, i=None, elements=None, o=None): - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - self.comb +=[elements[0].i.eq(self.i)] - self.comb +=[elements[i+1].i.eq(elements[i].o) for i in range(len(elements)-1)] - self.comb +=[self.o.eq(elements[len(elements)-1].o)] - -class PwrOnRst(Module): - def __init__(self, width, rst=None, simulation=False): - self.rst = ifthenelse(rst, rst, Signal()) - ### - cnt = Signal(width) - sync_no_reset = [If(self.rst, cnt.eq(cnt+1))] - if not simulation: - self.comb +=[ - If(cnt >= (2**width-1), - self.rst.eq(0) - ).Else( - self.rst.eq(1) - ) - ] - else: - self.comb += self.rst.eq(0) - self._fragment += Fragment(sync={"sys_no_reset" : sync_no_reset}) \ No newline at end of file diff --git a/examples/de0_nano/top.py b/examples/de0_nano/top.py index cc363f26..94622eaf 100644 --- a/examples/de0_nano/top.py +++ b/examples/de0_nano/top.py @@ -14,13 +14,16 @@ #============================================================================== # I M P O R T #============================================================================== -from migen.fhdl.structure import * -from migen.fhdl.module import * +from migen.fhdl.std import * from migen.bus import csr +from migen.bank import csrgen +from miscope.std.misc import * -from miscope import trigger, recorder, miio, mila -from miscope.bridges import uart2csr -from miscope.tools.misc import * +from miscope.triggering import * +from miscope.recording import * +from miscope import miio, mila + +from miscope.com import uart2csr from timings import * @@ -31,10 +34,6 @@ from timings import * # Timings Param clk_freq = 50*MHz -# Csr Addr -MIIO_ADDR = 0x00 -MILA_ADDR = 0x01 - # Mila Param trig_w = 16 dat_w = 16 @@ -44,16 +43,23 @@ rec_size = 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.MiIo(MIIO_ADDR, 8, "IO") + self.submodules.miio = miio.MiIo(8) # MiLa - self.submodules.term = trigger.Term(trig_w) - self.submodules.trigger = trigger.Trigger(trig_w, [self.term]) - self.submodules.recorder = recorder.Recorder(dat_w, rec_size) + term = Term(trig_w) + trigger = Trigger(trig_w, [term]) + recorder = Recorder(dat_w, rec_size) - self.submodules.mila = mila.MiLa(MILA_ADDR, self.trigger, self.recorder, trig_is_dat=True) + self.submodules.mila = mila.MiLa(trigger, recorder) # Uart2Csr self.submodules.uart2csr = uart2csr.Uart2Csr(clk_freq, 115200) @@ -62,15 +68,12 @@ class SoC(Module): self.comb += self.uart2csr.rx.eq(uart_pads.rx) # Csr Interconnect - self.submodules.csrcon = csr.Interconnect(self.uart2csr.csr, - [ - self.miio.bank.bus, - self.trigger.bank.bus, - self.recorder.bank.bus - ]) + 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 = platform.request("user_led", 0, 8) + self.led = Cat(*[platform.request("user_led", i) for i in range(8)]) # Misc self.cnt = Signal(9) @@ -94,7 +97,8 @@ class SoC(Module): # Mila # self.comb +=[ - self.mila.trig.eq(Cat( + self.mila.sink.stb.eq(1), + self.mila.sink.payload.d.eq(Cat( self.freqgen.o, self.eventgen_rising.o, self.eventgen_falling.o, diff --git a/miscope/bridges/__init__.py b/miscope/bridges/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/miscope/bridges/spi2csr/__init__.py b/miscope/bridges/spi2csr/__init__.py deleted file mode 100644 index 2416cb6c..00000000 --- a/miscope/bridges/spi2csr/__init__.py +++ /dev/null @@ -1,135 +0,0 @@ -from migen.fhdl.structure import * -from migen.genlib.misc import * -from migen.genlib.cdc import * -from migen.bus import csr - -class Spi2Csr(Module): - def __init__(self, burst_length=8): - self.a_w = 14 - self.d_w = 8 - self.burst_length = 8 - - # Csr interface - self.csr = csr.Interface() - - # Spi interface - self.spi_clk = Signal() - self.spi_cs_n = Signal(reset=1) - self.spi_mosi = Signal() - self.spi_miso = Signal() - - ### - - # Resychronisation - clk_synchro = Synchronizer(i=self.spi_clk) - cs_n_synchro = Synchronizer(i=self.spi_cs_n) - mosi_synchro = Synchronizer(i=self.spi_mosi) - - self.specials += {clk_synchro, cs_n_synchro, mosi_synchro} - - # Decode - spi_clk_rising = Signal() - spi_clk_falling = Signal() - spi_cs_n_active = Signal() - spi_mosi_dat = Signal() - - self.specials += RisingEdge(i=clk_synchro.o, o=spi_clk_rising) - self.specials += FallingEdge(i=clk_synchro.o, o=spi_clk_falling) - - self.sync +=[ - spi_cs_n_active.eq(~cs_n_synchro.o), - spi_mosi_dat.eq(~mosi_synchro.o), - ] - - # - # Spi --> Csr - # - spi_cnt = Signal(bits_for(self.a_w + self.burst_length*self.d_w)) - spi_addr = Signal(self.a_w) - spi_w_dat = Signal(self.d_w) - spi_r_dat = Signal(self.d_w) - spi_we = Signal() - spi_re = Signal() - spi_we_re_done = Signal(reset=1) - spi_miso_dat = Signal() - - # Re/We Signals Decoding - first_b = Signal() - last_b = Signal() - - self.comb +=[ - first_b.eq(spi_cnt[0:bits_for(self.d_w)-1] == 0), - last_b.eq(spi_cnt[0:bits_for(self.d_w)-1] == 2**(bits_for(self.d_w-1))-1) - ] - self.sync +=[ - If((spi_cnt >= (self.a_w + self.d_w)) & first_b, - spi_we.eq(spi_addr[self.a_w-1] & ~spi_we_re_done), - spi_re.eq(~spi_addr[self.a_w-1] & ~spi_we_re_done), - spi_we_re_done.eq(1) - ).Elif((spi_cnt >= self.a_w) & first_b, - spi_re.eq(~spi_addr[self.a_w-1] & ~spi_we_re_done), - spi_we_re_done.eq(1) - ).Else( - spi_we.eq(0), - spi_re.eq(0), - spi_we_re_done.eq(0) - ) - ] - - # Spi Addr / Data Decoding - self.sync +=[ - If(~spi_cs_n_active, - spi_cnt.eq(0), - ).Elif(spi_clk_rising, - # addr - If(spi_cnt < self.a_w, - spi_addr.eq(Cat(spi_mosi_dat,spi_addr[:self.a_w-1])) - ).Elif((spi_cnt >= (self.a_w+self.d_w)) & last_b, - spi_addr.eq(spi_addr+1) - ).Elif((spi_cnt >= self.a_w) & last_b & (spi_addr[self.a_w-1] == 0), - spi_addr.eq(spi_addr+1) - ), - # dat - If(spi_cnt >= self.a_w, - spi_w_dat.eq(Cat(spi_mosi_dat,spi_w_dat[:self.d_w-1])) - ), - - # spi_cnt - spi_cnt.eq(spi_cnt+1) - ) - ] - - # - # Csr --> Spi - # - spi_r_dat_shift = Signal(self.d_w) - self.sync +=[ - If(spi_re, - spi_r_dat_shift.eq(spi_r_dat) - ), - - If(~spi_cs_n_active, - spi_miso_dat.eq(0) - ).Elif(spi_clk_falling, - spi_miso_dat.eq(spi_r_dat_shift[self.d_w-1]), - spi_r_dat_shift.eq(Cat(0,spi_r_dat_shift[:self.d_w-1])) - ) - ] - - - # - # Csr Interface - # - self.comb += [ - self.csr.adr.eq(spi_addr), - self.csr.dat_w.eq(spi_w_dat), - self.csr.we.eq(spi_we) - ] - - # - # Spi Interface - # - self.comb += [ - spi_r_dat.eq(self.csr.dat_r), - self.spi_miso.eq(spi_miso_dat) - ] \ No newline at end of file diff --git a/miscope/bridges/spi2csr/tools/__init__.py b/miscope/bridges/spi2csr/tools/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/miscope/bridges/spi2csr/tools/arduino/spiFpga.cpp b/miscope/bridges/spi2csr/tools/arduino/spiFpga.cpp deleted file mode 100644 index 0787072e..00000000 --- a/miscope/bridges/spi2csr/tools/arduino/spiFpga.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * spiFpga - * Copyright (C) 2012 by Florent Kermarrec - * Copyright (C) 2011 by James Bowman - * - */ - -#include "WProgram.h" -#include -#include -#include - -SFClass SF; - -void SFClass::begin() -{ - pinMode(SS_PIN, OUTPUT); - SPI.begin(); - SPI.setClockDivider(SPI_CLOCK_DIV2); - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - SPSR = (1 << SPI2X); - digitalWrite(SS_PIN, HIGH); -} - -void SFClass::end() { -} - -void SFClass::__start(unsigned int addr) -{ - digitalWrite(SS_PIN, LOW); - SPI.transfer(highByte(addr)); - SPI.transfer(lowByte(addr)); -} - -void SFClass::__wstart(unsigned int addr) -{ - __start(0x8000|addr); -} - -void SFClass::__end() -{ - digitalWrite(SS_PIN, HIGH); -} - -char SFClass::rd(unsigned int addr) -{ - __start(addr); - char r = SPI.transfer(0); - __end(); - return r; -} - -void SFClass::wr(unsigned int addr, char v) -{ - __wstart(addr); - SPI.transfer(v); - __end(); -} \ No newline at end of file diff --git a/miscope/bridges/spi2csr/tools/arduino/spiFpga.h b/miscope/bridges/spi2csr/tools/arduino/spiFpga.h deleted file mode 100644 index c28837b2..00000000 --- a/miscope/bridges/spi2csr/tools/arduino/spiFpga.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * spiFpga - * Copyright (C) 2012 by Florent Kermarrec - * Copyright (C) 2011 by James Bowman - * - */ - -#ifndef _SF_H_INCLUDED -#define _SF_H_INCLUDED - -#ifndef SS_PIN -#define SS_PIN 10 -#endif - -class SFClass { -public: - static void begin(); - static void end(); - static void __start(unsigned int addr); - static void __wstart(unsigned int addr); - static void __end(void); - static char rd(unsigned int addr); - static void wr(unsigned int addr, char v); -}; - -extern SFClass SF; - -#endif diff --git a/miscope/bridges/spi2csr/tools/arduino/uart2Spi.pde b/miscope/bridges/spi2csr/tools/arduino/uart2Spi.pde deleted file mode 100644 index df049bfd..00000000 --- a/miscope/bridges/spi2csr/tools/arduino/uart2Spi.pde +++ /dev/null @@ -1,51 +0,0 @@ -/* - Uart2Spi - Copyright 2012 - Florent Kermarrec - florent@enjoy-digital.fr - - Protocol: - -Write : 0x01 + 16b Addr + 8b Data - -Read : 0x02 + 16b Addr + 8b Don't Care - - Todo: - Support Spi Burst Mode - - */ -#include -#include - -void setup() { - SF.begin(); - SPI.setClockDivider(8); - Serial.begin(115200); -} - -int cmd = 0; - -void loop() -{ - if (Serial.available() == 4) - { - cmd = Serial.read(); - //Write Cmd - if (cmd == 0x01) - { - char addrMsb = Serial.read(); - char addrLsb = Serial.read(); - char data = Serial.read(); - SF.wr(addrMsb<<8|addrLsb, data); - } - //Read Cmd - if (cmd == 0x02) - { - char addrMsb = Serial.read(); - char addrLsb = Serial.read(); - Serial.read(); - char data; - data = SF.rd(addrMsb<<8|addrLsb); - Serial.print(data); - } - else { - Serial.flush(); - } - } -} \ No newline at end of file diff --git a/miscope/bridges/spi2csr/tools/uart2Spi.py b/miscope/bridges/spi2csr/tools/uart2Spi.py deleted file mode 100644 index c7326c70..00000000 --- a/miscope/bridges/spi2csr/tools/uart2Spi.py +++ /dev/null @@ -1,56 +0,0 @@ -import string -import time -import serial -from struct import * -from migen.fhdl.structure import * - -def write_b(uart, data): - uart.write(pack('B',data)) - -class Uart2Spi: - 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 read(self, addr): - write_b(self.uart, 0x02) - write_b(self.uart, (addr>>8)&0xFF) - write_b(self.uart, (addr&0xFF)) - write_b(self.uart, 0x00) - read = self.uart.read() - if self.debug: - print("RD @ %04X" %addr) - return int(read[0]) - - 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(self, addr, data): - write_b(self.uart, 0x01) - write_b(self.uart, (addr>>8)&0xFF) - write_b(self.uart, (addr&0xFF)) - write_b(self.uart, data) - if self.debug: - print("WR %02X @ %04X" %(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/bridges/uart2csr/__init__.py b/miscope/bridges/uart2csr/__init__.py deleted file mode 100644 index a9c20fa6..00000000 --- a/miscope/bridges/uart2csr/__init__.py +++ /dev/null @@ -1,186 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.module import * -from migen.bus import csr -from migen.genlib.fsm import * - -from miscope.bridges.uart2csr.uart import * - -WRITE_CMD = 0x01 -READ_CMD = 0x02 -CLOSE_CMD = 0x03 - -class Uart2Csr(Module): - def __init__(self, clk_freq, baud): - # Uart interface - self.rx = Signal() - self.tx = Signal() - - # Csr interface - self.csr = csr.Interface() - - ### - - self.submodules.uart = UART(clk_freq, baud) - uart = self.uart - - # - # In/Out - # - self.comb +=[ - uart.rx.eq(self.rx), - self.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("IDLE", - "GET_BL", "GET_ADDR", - "GET_DATA", "WRITE_CSR", - "READ_CSR0", "READ_CSR1", "SEND_DATA") - - fsm = self.fsm - - # - # Global - # - self.sync +=[ - If(fsm.ongoing(fsm.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(fsm.IDLE, - If(uart.rx_ev & ((uart.rx_dat == WRITE_CMD) | (uart.rx_dat == READ_CMD)), - fsm.next_state(fsm.GET_BL) - ) - ) - - self.sync += If(fsm.ongoing(fsm.IDLE) & uart.rx_ev, cmd.eq(uart.rx_dat)) - - # - # Get burst length - # - fsm.act(fsm.GET_BL, - If(get_bl_done, - fsm.next_state(fsm.GET_ADDR) - ) - ) - - self.comb += get_bl_done.eq(uart.rx_ev & fsm.ongoing(fsm.GET_BL)) - - self.sync += If(get_bl_done, burst_cnt.eq(uart.rx_dat)) - - # - # Get address - # - fsm.act(fsm.GET_ADDR, - If(get_addr_done & (cmd == WRITE_CMD), - fsm.next_state(fsm.GET_DATA) - ).Elif(get_addr_done & (cmd == READ_CMD), - fsm.next_state(fsm.READ_CSR0) - ) - ) - - self.comb += get_addr_done.eq(uart.rx_ev & (cnt == 4) & fsm.ongoing(fsm.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(fsm.WRITE_CSR) | send_data_done, - addr.eq(addr + 1) - ) - ] - - # - # Get data - # - fsm.act(fsm.GET_DATA, - If(get_data_done, - fsm.next_state(fsm.WRITE_CSR) - ) - ) - - self.comb += get_data_done.eq(uart.rx_ev & fsm.ongoing(fsm.GET_DATA)) - self.sync += [ - If(get_data_done, - burst_cnt.eq(burst_cnt-1), - data.eq(uart.rx_dat) - ) - ] - - # - # Write Csr - # - fsm.act(fsm.WRITE_CSR, - If((burst_cnt==0), - fsm.next_state(fsm.IDLE) - ).Else(fsm.next_state(fsm.GET_DATA)) - ) - - - # - # Read Csr0 - # - fsm.act(fsm.READ_CSR0, - fsm.next_state(fsm.READ_CSR1) - ) - - self.sync += If(fsm.entering(fsm.READ_CSR0), burst_cnt.eq(burst_cnt-1)) - - # - # Read Csr1 - # - fsm.act(fsm.READ_CSR1, - fsm.next_state(fsm.SEND_DATA) - ) - - - # - # Send Data - # - fsm.act(fsm.SEND_DATA, - If(send_data_done & (burst_cnt==0), - fsm.next_state(fsm.IDLE) - ).Elif(send_data_done, - fsm.next_state(fsm.READ_CSR0) - ) - ) - - self.comb += send_data_done.eq(fsm.ongoing(fsm.SEND_DATA) & uart.tx_ev) - - self.sync += [ - uart.tx_dat.eq(self.csr.dat_r), - uart.tx_we.eq(fsm.entering(fsm.SEND_DATA)), - ] - - - # - # Csr access - # - self.comb += self.csr.adr.eq(addr) - self.sync +=[ - self.csr.dat_w.eq(data), - If(fsm.ongoing(fsm.WRITE_CSR), - self.csr.we.eq(1) - ).Else( - self.csr.we.eq(0) - ) - ] \ No newline at end of file diff --git a/miscope/bridges/uart2csr/tools/__init__.py b/miscope/bridges/uart2csr/tools/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/miscope/bridges/uart2csr/tools/uart2Csr.py b/miscope/bridges/uart2csr/tools/uart2Csr.py deleted file mode 100644 index 1e58d946..00000000 --- a/miscope/bridges/uart2csr/tools/uart2Csr.py +++ /dev/null @@ -1,82 +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 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(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(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)): - 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/bridges/uart2csr/uart.py b/miscope/bridges/uart2csr/uart.py deleted file mode 100644 index fe2e9e06..00000000 --- a/miscope/bridges/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/__init__.py b/miscope/com/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/miscope/com/uart2csr/__init__.py b/miscope/com/uart2csr/__init__.py new file mode 100644 index 00000000..e8e569ce --- /dev/null +++ b/miscope/com/uart2csr/__init__.py @@ -0,0 +1,183 @@ +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, clk_freq, baud): + # Uart interface + self.rx = Signal() + self.tx = Signal() + + # Csr interface + self.csr = csr.Interface() + + ### + + self.submodules.uart = UART(clk_freq, baud) + uart = self.uart + + # + # In/Out + # + self.comb +=[ + uart.rx.eq(self.rx), + self.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 new file mode 100644 index 00000000..e69de29b diff --git a/miscope/com/uart2csr/host/uart2csr.py b/miscope/com/uart2csr/host/uart2csr.py new file mode 100644 index 00000000..c1ce7d08 --- /dev/null +++ b/miscope/com/uart2csr/host/uart2csr.py @@ -0,0 +1,91 @@ +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 new file mode 100644 index 00000000..fe2e9e06 --- /dev/null +++ b/miscope/com/uart2csr/uart.py @@ -0,0 +1,107 @@ +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/miio.py b/miscope/miio.py index b2512cb5..d4bd1bd9 100644 --- a/miscope/miio.py +++ b/miscope/miio.py @@ -3,44 +3,17 @@ from migen.bus import csr from migen.bank import csrgen from migen.bank.description import * -from miscope.tools.misc import * - -class MiIo: - # - # Definition - # - def __init__(self, address, width, mode="IO", interface=None): - self.address = address +class MiIo(Module, AutoCSR): + def __init__(self, width): self.width = width - self.mode = mode.upper() - self.interface = interface - self.words = int((2**bits_for(width-1))/8) - - if "I" in self.mode: - self.i = Signal(self.width) - self._r_i = CSRStatus(self.width) - - if "O" in self.mode: - self.o = Signal(self.width) - self._r_o = CSRStorage(self.width) - - self.bank = csrgen.Bank([self._r_o, self._r_i], address=self.address) - - def get_fragment(self): - comb = [] - - if "I" in self.mode: - comb += [self._r_i.status.eq(self.i)] - - if "O" in self.mode: - comb += [self.o.eq(self._r_o.storage)] - - return Fragment(comb) + self.bank.get_fragment() - # - # Driver - # - def set(self, data): - self.interface.write(get_csr_base(self.bank), data) - - def get(self): - return self.interface.read(get_csr_base(self.bank) + self.words) \ No newline at end of file + + self.i = Signal(self.width) + self.o = Signal(self.width) + + self._r_i = CSRStatus(self.width) + self._r_o = CSRStorage(self.width) + + self.sync +=[ + self._r_i.status.eq(self.i), + self.o.eq(self._r_o.storage) + ] \ No newline at end of file diff --git a/miscope/mila.py b/miscope/mila.py index 341b135a..b0aa15aa 100644 --- a/miscope/mila.py +++ b/miscope/mila.py @@ -1,48 +1,27 @@ from migen.fhdl.structure import * +from migen.flow.actor import * +from migen.flow.network import * from migen.bus import csr from migen.bank import description, csrgen from migen.bank.description import * -from miscope import trigger, recorder -from miscope.tools.misc import * - -class MiLa: - def __init__(self, address, trigger, recorder, interface=None, trig_is_dat=False): - +class MiLa(Module, AutoCSR): + def __init__(self, trigger, recorder): self.trigger = trigger self.recorder = recorder - self.interface = interface - self.trig_is_dat = trig_is_dat - - self.stb = Signal(reset=1) - self.trig = Signal(self.trigger.width) - self.dat = Signal(self.recorder.width) - - self.set_address(address) - self.set_interface(interface) - def set_address(self, address): - self.address = address - self.trigger.set_address(self.address) - self.recorder.set_address(self.address + 0x01) + self.sink = trigger.sink + self.submodules += trigger, recorder - def set_interface(self, interface): - self.interface = interface - self.trigger.set_interface(interface) - self.recorder.set_interface(interface) - - def get_fragment(self): - comb =[ - self.recorder.stb.eq(self.stb), - self.trigger.trig.eq(self.trig), + self.comb +=[ + recorder.sink.stb.eq(trigger.source.stb), - self.recorder.hit.eq(self.trigger.hit) + recorder.sink.payload.hit.eq(trigger.source.payload.hit), + trigger.source.ack.eq(recorder.sink.ack) ] - if self.trig_is_dat: - comb +=[ - self.recorder.dat.eq(self.trig), - ] - else: - self.recorder.dat.eq(self.dat), - - return Fragment(comb) \ No newline at end of file + + # Todo; Insert configurable delay to support pipelined + # triggers elements + self.comb +=[ + recorder.sink.payload.d.eq(self.sink.payload.d), + ] \ No newline at end of file diff --git a/miscope/recorder.py b/miscope/recorder.py deleted file mode 100644 index 87b7bf3d..00000000 --- a/miscope/recorder.py +++ /dev/null @@ -1,324 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.specials import Memory -from migen.bus import csr -from migen.bank import description, csrgen -from migen.bank.description import * -from migen.genlib.misc import optree -from migen.genlib.fsm import * - -from miscope.tools.misc import * - -class Storage: - # - # Definition - # - def __init__(self, width, depth): - self.width = width - self.depth = depth - self.depth_width = bits_for(self.depth) - - # Control - self.rst = Signal() - self.start = Signal() - self.offset = Signal(self.depth_width) - self.size = Signal(self.depth_width) - self.done = Signal() - - # Push Path - self.push_stb = Signal() - self.push_dat = Signal(self.width) - self._push_ptr = Signal(self.depth_width) - self._push_ptr_stop = Signal(self.depth_width) - - # Pull Path - self.pull_stb = Signal() - self.pull_dat = Signal(self.width) - self._pull_ptr = Signal(self.depth_width) - - # Memory - self._mem = Memory(self.width, self.depth) - self._push_port = self._mem.get_port(write_capable=True) - self._pull_port = self._mem.get_port(has_re=True) - - def get_fragment(self): - comb = [ - self._push_port.adr.eq(self._push_ptr), - self._push_port.we.eq(self.push_stb), - self._push_port.dat_w.eq(self.push_dat), - - self._pull_port.adr.eq(self._pull_ptr), - self._pull_port.re.eq(self.pull_stb), - self.pull_dat.eq(self._pull_port.dat_r) - ] - - # FSM - fsm = FSM("IDLE", "ACTIVE") - - # Idle - fsm.act(fsm.IDLE, - If(self.start, - fsm.next_state(fsm.ACTIVE), - ) - ) - - # Active - fsm.act(fsm.ACTIVE, - If(self.done | self.rst, - fsm.next_state(fsm.IDLE), - ) - ) - - sync =[ - If(fsm.entering(fsm.ACTIVE), - self._push_ptr_stop.eq(self._push_ptr + self.size - self.offset), - self._pull_ptr.eq(self._push_ptr - self.offset - 1) - ).Else( - If(self.pull_stb, self._pull_ptr.eq(self._pull_ptr + 1)) - ), - If(self.push_stb, self._push_ptr.eq(self._push_ptr + 1)), - ] - comb +=[self.done.eq((self._push_ptr == self._push_ptr_stop) & fsm.ongoing(fsm.ACTIVE))] - - return Fragment(comb, sync, specials={self._mem}) + fsm.get_fragment() - -class RLE: - - # - # Definition - # - def __init__(self, width, length): - self.width = width - self.length = length - - # Control - self.enable = Signal() - - # Input - self.stb_i = Signal() - self.dat_i = Signal(width) - - # Output - self.stb_o = Signal() - self.dat_o = Signal(width) - - def get_fragment(self): - - # Register Input - stb_i_d = Signal() - dat_i_d = Signal(self.width) - - sync =[dat_i_d.eq(self.dat_i)] - sync +=[stb_i_d.eq(self.stb_i)] - - # Detect diff - diff = Signal() - comb = [diff.eq(self.stb_i & (~self.enable | (dat_i_d != self.dat_i)))] - - diff_rising = RisingEdge(diff) - diff_d = Signal() - sync +=[diff_d.eq(diff)] - - # Generate RLE word - rle_cnt = Signal(max=self.length) - rle_max = Signal() - - comb +=[If(rle_cnt == self.length, rle_max.eq(self.enable))] - - sync +=[ - If(diff | rle_max, - rle_cnt.eq(0) - ).Else( - rle_cnt.eq(rle_cnt + 1) - ) - ] - - # Mux RLE word and data - comb +=[ - If(diff_rising.o & (~rle_max), - self.stb_o.eq(1), - self.dat_o[self.width-1].eq(1), - self.dat_o[:flen(rle_cnt)].eq(rle_cnt) - ).Elif(diff_d | rle_max, - self.stb_o.eq(stb_i_d), - self.dat_o.eq(dat_i_d) - ).Else( - self.stb_o.eq(0), - ) - ] - - return Fragment(comb, sync) + diff_rising.get_fragment() - -class Sequencer: - # - # Definition - # - def __init__(self): - - # Control - self.rst = Signal() - self.arm = Signal() - - # Trigger - self.hit = Signal() - - # Recorder - self.start = Signal() - self.done = Signal() - - # Internal - self.enable = Signal() - - def get_fragment(self): - - # FSM - fsm = FSM("IDLE", "ACTIVE") - - # Idle - fsm.act(fsm.IDLE, - If(self.arm, - fsm.next_state(fsm.ACTIVE), - ) - ) - - # Active - fsm.act(fsm.ACTIVE, - If(self.done | self.rst, - fsm.next_state(fsm.IDLE), - ), - self.enable.eq(1) - ) - - # Start - hit_rising = RisingEdge(self.hit) - comb =[self.start.eq(self.enable & hit_rising.o)] - - return Fragment(comb) + fsm.get_fragment() + hit_rising.get_fragment() - - -REC_RST_BASE = 0x00 -REC_RLE_BASE = 0x01 -REC_ARM_BASE = 0x02 -REC_DONE_BASE = 0x03 -REC_SIZE_BASE = 0x04 -REC_OFFSET_BASE = 0x06 -REC_READ_BASE = 0x08 -REC_READ_DATA_BASE = 0x09 - -class Recorder: - # - # Definition - # - def __init__(self, width, depth, address=0x0000, interface=None): - self.width = width - self.depth = depth - self.depth_width = bits_for(self.depth-1) - - self.storage = Storage(self.width, self.depth) - self.sequencer = Sequencer() - self.rle = RLE(self.width, (2**(width-2))) - - # csr interface - self._r_rst = CSRStorage(reset=1) - self._r_rle = CSRStorage(reset=0) - self._r_arm = CSRStorage(reset=0) - self._r_done = CSRStatus() - - self._r_size = CSRStorage(self.depth_width, reset=1) - self._r_offset = CSRStorage(self.depth_width, reset=1) - - self._r_pull_stb = CSRStorage(reset=0) - self._r_pull_dat = CSRStatus(self.width) - - self.regs = [self._r_rst, self._r_rle, self._r_arm, self._r_done, self._r_size, self._r_offset, - self._r_pull_stb, self._r_pull_dat] - - # set address / interface - self.set_address(address) - self.set_interface(interface) - - # trigger Interface - self.hit = Signal() - self.stb = Signal() - self.dat = Signal(self.width) - - def set_address(self, address): - self.address = address - self.bank = csrgen.Bank(self.regs, address=self.address) - - def set_interface(self, interface): - self.interface = interface - - def get_fragment(self): - - _pull_stb_rising = RisingEdge(self._r_pull_stb.storage) - - # Bank <--> Storage / Sequencer - comb = [ - self.sequencer.rst.eq(self._r_rst.storage), - self.storage.rst.eq(self._r_rst.storage), - - self.rle.enable.eq(self._r_rle.storage), - self.sequencer.arm.eq(self._r_arm.storage), - self.storage.offset.eq(self._r_offset.storage), - self.storage.size.eq(self._r_size.storage), - - self._r_done.status.eq(~self.sequencer.enable), - - self.storage.pull_stb.eq(_pull_stb_rising.o), - self._r_pull_dat.status.eq(self.storage.pull_dat) - ] - - # Storage <--> Sequencer <--> Trigger - comb += [ - self.storage.start.eq(self.sequencer.start), - self.sequencer.done.eq(self.storage.done), - self.sequencer.hit.eq(self.hit), - - self.rle.stb_i.eq(self.stb), - self.rle.dat_i.eq(self.dat), - - self.storage.push_stb.eq(self.sequencer.enable & self.rle.stb_o), - self.storage.push_dat.eq(self.rle.dat_o) - ] - - return self.bank.get_fragment() + Fragment(comb) +\ - self.storage.get_fragment() + self.sequencer.get_fragment() +\ - _pull_stb_rising.get_fragment() + self.rle.get_fragment() - - - - # - # Driver - # - def reset(self): - self.interface.write(get_csr_base(self.bank) + REC_RST_BASE, 1) - self.interface.write(get_csr_base(self.bank) + REC_RST_BASE, 0) - - def enable_rle(self): - self.interface.write(get_csr_base(self.bank) + REC_RLE_BASE, 1) - - def disable_rle(self): - self.interface.write(get_csr_base(self.bank) + REC_RLE_BASE, 0) - - def arm(self): - self.interface.write(get_csr_base(self.bank) + REC_ARM_BASE, 1) - self.interface.write(get_csr_base(self.bank) + REC_ARM_BASE, 0) - - def is_done(self): - return self.interface.read(get_csr_base(self.bank) + REC_DONE_BASE) == 1 - - def set_size(self, dat): - self.interface.write_n(get_csr_base(self.bank) + REC_SIZE_BASE, dat, 16) - - def set_offset(self, dat): - self.interface.write_n(get_csr_base(self.bank) + REC_OFFSET_BASE, dat, 16) - - def pull(self, size): - r = [] - for i in range(size): - self.interface.write(get_csr_base(self.bank) + REC_READ_BASE, 1) - self.interface.write(get_csr_base(self.bank) + REC_READ_BASE, 0) - r.append(self.interface.read_n(get_csr_base(self.bank) + REC_READ_DATA_BASE, self.width)) - if i%128 == 0: - print(i) - return r diff --git a/miscope/recording/__init__.py b/miscope/recording/__init__.py new file mode 100644 index 00000000..064991cd --- /dev/null +++ b/miscope/recording/__init__.py @@ -0,0 +1,86 @@ +from migen.fhdl.std import * +from migen.flow.actor import * +from migen.flow.network import * +from migen.fhdl.specials import Memory +from migen.bus import csr +from migen.bank import description, csrgen +from migen.bank.description import * +from migen.actorlib.fifo import SyncFIFO + +class Recorder(Module, AutoCSR): + def __init__(self, width, depth): + self.width = width + + self.sink = Sink([("hit", 1), ("d", width)]) + + self._r_trigger = CSR() + self._r_length = CSRStorage(bits_for(depth)) + self._r_offset = CSRStorage(bits_for(depth)) + self._r_done = CSRStatus() + + self._r_read_en = CSR() + self._r_read_empty = CSRStatus() + self._r_read_dat = CSRStatus(width) + + ### + + length = self._r_length.storage + offset = self._r_offset.storage + done = Signal(reset=1) + ongoing = Signal() + + cnt = Signal(max=depth) + + fifo = SyncFIFO([("d", width)], depth) + self.submodules += fifo + + # Write fifo is done only when done = 0 + # Fifo must always be pulled by software between + # acquisition (Todo: add a flush funtionnality) + self.comb +=[ + fifo.sink.stb.eq(self.sink.stb & ~done), + fifo.sink.payload.d.eq(self.sink.payload.d), + self.sink.ack.eq(1) + ] + + # Done, Ongoing: + # 0, 0 : Storage triggered but hit was not yet seen + # Data are recorded to fifo, if "offset" datas + # in the fifo, ack is set on fifo.source to + # store only "offset" datas. + # + # 0, 1 : Hit was seen, ack is no longer set on fifo.source + # we are storing "length"-"offset" data in this + # phase + # + # 1, 0 : We have stored "length" datas in fifo. Write to + # fifo is disabled. + # Software must now read data from the fifo until + # it is empty + + # done & ongoing + self.sync += [ + If(self._r_trigger.re & self._r_trigger.r, done.eq(0) + ).Elif(cnt==length, done.eq(1)), + + If(self.sink.stb & self.sink.payload.hit & ~done, ongoing.eq(1) + ).Elif(done, ongoing.eq(0)), + ] + + # fifo ack & csr connection + self.comb += [ + If(~done & ~ongoing & (cnt >= offset), fifo.source.ack.eq(1) + ).Else(fifo.source.ack.eq(self._r_read_en.re & self._r_read_en.r)), + self._r_read_empty.status.eq(~fifo.source.stb), + self._r_read_dat.status.eq(fifo.source.payload.d), + self._r_done.status.eq(done) + ] + + # cnt + self.sync += [ + If(done == 1, + cnt.eq(0) + ).Elif(fifo.sink.stb & fifo.sink.ack & ~(fifo.source.stb & fifo.source.ack), + cnt.eq(cnt+1), + ) + ] \ No newline at end of file diff --git a/miscope/std/__init__.py b/miscope/std/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/miscope/std/cif.py b/miscope/std/cif.py new file mode 100644 index 00000000..5300908e --- /dev/null +++ b/miscope/std/cif.py @@ -0,0 +1,94 @@ +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/conv.py b/miscope/std/conv.py new file mode 100644 index 00000000..66b88db8 --- /dev/null +++ b/miscope/std/conv.py @@ -0,0 +1,11 @@ +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) diff --git a/miscope/std/misc.py b/miscope/std/misc.py new file mode 100644 index 00000000..359f8f56 --- /dev/null +++ b/miscope/std/misc.py @@ -0,0 +1,114 @@ +from migen.fhdl.std import * + +def ifthenelse(cond, r1, r2): + if cond != False and cond is not None: + return r1 + else: + return r2 + +class RisingEdge(Module): + def __init__(self, i=None, o=None): + self.i = ifthenelse(i, i, Signal()) + self.o = ifthenelse(o, 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, i=None, o=None, domain="sys"): + self.i = ifthenelse(i, i, Signal()) + self.o = ifthenelse(o, 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, o=None): + cnt_max = int(clk_freq/freq/2) + width = bits_for(cnt_max) + + self.o = ifthenelse(o, o, Signal()) + #### + cnt = Signal(width) + 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, i=None, level=1, clk_freq=0, length=1, o=None): + + cnt_max = int(length*clk_freq) + width = bits_for(cnt_max) + + self.i = ifthenelse(i, i, Signal()) + self.o = ifthenelse(o, o, Signal()) + ### + cnt = Signal(width) + i_edge = Signal() + + if level == RISING_EDGE: + self.submodules += RisingEdge(self.i, i_edge) + elif level == FALLING_EDGE: + self.submodules += FallingEdge(self.i, i_edge) + + self.sync += [ + If(i_edge == 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, o=None): + self.ratio = Signal(width) + self.o = ifthenelse(o, 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) + ] + +class Cascade(Module): + def __init__(self, i=None, elements=None, o=None): + self.i = ifthenelse(i, i, Signal()) + self.o = ifthenelse(o, o, Signal()) + self.comb +=[elements[0].i.eq(self.i)] + self.comb +=[elements[i+1].i.eq(elements[i].o) for i in range(len(elements)-1)] + self.comb +=[self.o.eq(elements[len(elements)-1].o)] + +class PwrOnRst(Module): + def __init__(self, width, rst=None, simulation=False): + self.rst = ifthenelse(rst, rst, Signal()) + ### + cnt = Signal(width) + sync_no_reset = [If(self.rst, cnt.eq(cnt+1))] + if not simulation: + self.comb +=[ + If(cnt >= (2**width-1), + self.rst.eq(0) + ).Else( + self.rst.eq(1) + ) + ] + else: + self.comb += self.rst.eq(0) + self._fragment += Fragment(sync={"sys_no_reset" : sync_no_reset}) \ No newline at end of file diff --git a/miscope/std/truthtable.py b/miscope/std/truthtable.py new file mode 100644 index 00000000..14ce7969 --- /dev/null +++ b/miscope/std/truthtable.py @@ -0,0 +1,47 @@ +import os +import re +import sys + +def is_number(x): + try: + _ = float(x) + except ValueError: + return False + return True + +def remove_numbers(seq): + return [ x for x in seq if not is_number(x)] + +def remove_duplicates(seq): + seen = set() + seen_add = seen.add + return [ x for x in seq if x not in seen and not seen_add(x)] + +def get_operands(s): + operands = re.findall("[A-z0-9_]+", s) + operands = remove_duplicates(operands) + operands = remove_numbers(operands) + return sorted(operands) + +def gen_truth_table(s): + operands = get_operands(s) + width = len(operands) + stim = [] + for i in range(width): + stim_op = [] + for j in range(2**width): + stim_op.append((int(j/(2**i)))%2) + stim.append(stim_op) + + truth_table = [] + for i in range(2**width): + for j in range(width): + exec("%s = stim[j][i]" %operands[j]) + truth_table.append(eval(s) != 0) + return truth_table + +def main(): + print(gen_truth_table("(A&B&C)|D")) + +if __name__ == '__main__': + main() diff --git a/miscope/std/vcd.py b/miscope/std/vcd.py new file mode 100644 index 00000000..481a1238 --- /dev/null +++ b/miscope/std/vcd.py @@ -0,0 +1,234 @@ +import sys +import datetime + +from miscope.tools.conv import * + +def get_bits(values, width, low, high=None): + r = [] + for val in values: + t = dec2bin(val, width)[::-1] + if high == None: + t = t[low] + else: + t = t[low:high] + t = t[::1] + t = int(t,2) + r.append(t) + return r + +class VcdDat(list): + def __init__(self, width): + self.width = width + + def __getitem__(self, key): + if isinstance(key, int): + return get_bits(self, self.width, key) + elif isinstance(key, slice): + if key.start != None: + start = key.start + else: + start = 0 + if key.stop != None: + stop = key.stop + else: + stop = self.width + if stop > self.width: + stop = self.width + if key.step != None: + raise KeyError + return get_bits(self, self.width, start, stop) + else: + raise KeyError + + def decode_rle(self): + rle_bit = self[-1] + rle_dat = self[:self.width-1] + + dat = VcdDat(self.width) + i=0 + last = 0 + for d in self: + if rle_bit[i]: + if len(dat) >= 1: + # FIX ME... why is rle_dat in reverse orderd... + for j in range(int(dec2bin(rle_dat[i])[::-1],2)): + dat.append(last) + else: + dat.append(d) + last = d + i +=1 + return dat + +class Var: + def __init__(self, name, width, values=[], type="wire", default="x"): + self.type = type + self.width = width + self.name = name + self.val = default + self.values = values + self.vcd_id = None + + def set_vcd_id(self, s): + self.vcd_id = s + + def __len__(self): + return len(self.values) + + def change(self, cnt): + r = "" + try : + if self.values[cnt+1] != self.val: + r += "b" + r += dec2bin(self.values[cnt+1], self.width)[::-1] + r += " " + r += self.vcd_id + r += "\n" + return r + except : + return r + return r + +class Vcd: + def __init__(self, timescale="1ps", comment=""): + self.timescale = timescale + self.comment = comment + self.vars = [] + self.vcd_id = "!" + self.cnt = -1 + + def add(self, var): + var.set_vcd_id(self.vcd_id) + self.vcd_id = chr(ord(self.vcd_id)+1) + self.vars.append(var) + + def add_from_layout(self, layout, var): + i=0 + for s, n in layout: + self.add(Var(s, n, var[i:i+n])) + i += n + + def __len__(self): + l = 0 + for var in self.vars: + l = max(len(var),l) + return l + + def change(self): + r = "" + c = "" + for var in self.vars: + c += var.change(self.cnt) + if c != "": + r += "#" + r += str(self.cnt+1) + r += "\n" + r += c + return r + + def p_date(self): + now = datetime.datetime.now() + r = "$date\n" + r += "\t" + r += now.strftime("%Y-%m-%d %H:%M") + r += "\n" + r += "$end\n" + return r + + def p_version(self): + r = "$version\n" + r += "\tmiscope VCD dump\n" + r += "$end\n" + return r + + def p_comment(self): + r = "$comment\n" + r += self.comment + r += "\n$end\n" + return r + + def p_timescale(self): + r = "$timescale " + r += self.timescale + r += " $end\n" + return r + + def p_scope(self): + r = "$scope " + r += self.timescale + r += " $end\n" + return r + + def p_vars(self): + r = "" + for var in self.vars: + r += "$var " + r += var.type + r += " " + r += str(var.width) + r += " " + r += var.vcd_id + r += " " + r += var.name + r += " $end\n" + return r + + def p_unscope(self): + r = "$unscope " + r += " $end\n" + return r + + def p_enddefinitions(self): + r = "$enddefinitions " + r += " $end\n" + return r + + def p_dumpvars(self): + r = "$dumpvars\n" + for var in self.vars: + r += "b" + r += dec2bin(var.val, var.width) + r += " " + r += var.vcd_id + r+= "\n" + r += "$end\n" + return r + + def p_valuechange(self): + r = "" + for i in range(len(self)): + r += self.change() + self.cnt += 1 + return r + + def __repr__(self): + r = "" + r += self.p_date() + r += self.p_version() + r += self.p_comment() + r += self.p_timescale() + r += self.p_scope() + r += self.p_vars() + r += self.p_unscope() + r += self.p_enddefinitions() + r += self.p_dumpvars() + r += self.p_valuechange() + return r + + def write(self, filename): + f = open(filename, "w") + f.write(str(self)) + f.close() + +def main(): + myvcd = Vcd() + myvcd.add(Var(1, "foo1", [0,1,0,1,0,1])) + myvcd.add(Var(2, "foo2", [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0])) + myvcd.add(Var(3, "foo3")) + myvcd.add(Var(4, "foo4")) + ramp = [i%128 for i in range(1024)] + myvcd.add(Var(16, "ramp", ramp)) + print(myvcd) + +if __name__ == '__main__': + main() + diff --git a/miscope/tools/__init__.py b/miscope/tools/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/miscope/tools/conv.py b/miscope/tools/conv.py deleted file mode 100644 index 66b88db8..00000000 --- a/miscope/tools/conv.py +++ /dev/null @@ -1,11 +0,0 @@ -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) diff --git a/miscope/tools/misc.py b/miscope/tools/misc.py deleted file mode 100644 index 5e780a7e..00000000 --- a/miscope/tools/misc.py +++ /dev/null @@ -1,123 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.module import Module - -class RisingEdge(Module): - def __init__(self, i=None, o=None, domain="sys"): - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - #### - i_d = Signal() - sync =[i_d.eq(self.i)] - self.comb +=[self.o.eq(self.i & ~i_d)] - self._fragment += Fragment(sync={domain : sync}) - -class FallingEdge(Module): - def __init__(self, i=None, o=None, domain="sys"): - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - #### - i_d = Signal() - sync =[i_d.eq(self.i)] - self.comb +=[self.o.eq(~self.i & i_d)] - self._fragment += Fragment(sync={domain : sync}) - -class FreqGen(Module): - def __init__(self, clk_freq, freq, o=None): - cnt_max = int(clk_freq/freq/2) - width = bits_for(cnt_max) - - self.o = ifthenelse(o, o, Signal()) - #### - cnt = Signal(width) - 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, i=None, level=1, clk_freq=0, length=1, o=None): - - cnt_max = int(length*clk_freq) - width = bits_for(cnt_max) - - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - ### - cnt = Signal(width) - i_edge = Signal() - - if level == RISING_EDGE: - self.submodules += RisingEdge(self.i, i_edge) - elif level == FALLING_EDGE: - self.submodules += FallingEdge(self.i, i_edge) - - self.sync += [ - If(i_edge == 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, o=None): - self.ratio = Signal(width) - self.o = ifthenelse(o, 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) - ] - -class Cascade(Module): - def __init__(self, i=None, elements=None, o=None): - self.i = ifthenelse(i, i, Signal()) - self.o = ifthenelse(o, o, Signal()) - self.comb +=[elements[0].i.eq(self.i)] - self.comb +=[elements[i+1].i.eq(elements[i].o) for i in range(len(elements)-1)] - self.comb +=[self.o.eq(elements[len(elements)-1].o)] - -class PwrOnRst(Module): - def __init__(self, width, rst=None, simulation=False): - self.rst = ifthenelse(rst, rst, Signal()) - ### - cnt = Signal(width) - sync_no_reset = [If(self.rst, cnt.eq(cnt+1))] - if not simulation: - self.comb +=[ - If(cnt >= (2**width-1), - self.rst.eq(0) - ).Else( - self.rst.eq(1) - ) - ] - else: - self.comb += self.rst.eq(0) - self._fragment += Fragment(sync={"sys_no_reset" : sync_no_reset}) - -def get_csr_base(bank, name=None): - base = 0 - if name != None: - base = None - for i, c in enumerate(bank.simple_csrs): - if name in c.name: - if base == None: - base = i - elif base >= i: - base = i - return (bank.address<<9) + base \ No newline at end of file diff --git a/miscope/tools/truthtable.py b/miscope/tools/truthtable.py deleted file mode 100644 index 14ce7969..00000000 --- a/miscope/tools/truthtable.py +++ /dev/null @@ -1,47 +0,0 @@ -import os -import re -import sys - -def is_number(x): - try: - _ = float(x) - except ValueError: - return False - return True - -def remove_numbers(seq): - return [ x for x in seq if not is_number(x)] - -def remove_duplicates(seq): - seen = set() - seen_add = seen.add - return [ x for x in seq if x not in seen and not seen_add(x)] - -def get_operands(s): - operands = re.findall("[A-z0-9_]+", s) - operands = remove_duplicates(operands) - operands = remove_numbers(operands) - return sorted(operands) - -def gen_truth_table(s): - operands = get_operands(s) - width = len(operands) - stim = [] - for i in range(width): - stim_op = [] - for j in range(2**width): - stim_op.append((int(j/(2**i)))%2) - stim.append(stim_op) - - truth_table = [] - for i in range(2**width): - for j in range(width): - exec("%s = stim[j][i]" %operands[j]) - truth_table.append(eval(s) != 0) - return truth_table - -def main(): - print(gen_truth_table("(A&B&C)|D")) - -if __name__ == '__main__': - main() diff --git a/miscope/tools/vcd.py b/miscope/tools/vcd.py deleted file mode 100644 index 481a1238..00000000 --- a/miscope/tools/vcd.py +++ /dev/null @@ -1,234 +0,0 @@ -import sys -import datetime - -from miscope.tools.conv import * - -def get_bits(values, width, low, high=None): - r = [] - for val in values: - t = dec2bin(val, width)[::-1] - if high == None: - t = t[low] - else: - t = t[low:high] - t = t[::1] - t = int(t,2) - r.append(t) - return r - -class VcdDat(list): - def __init__(self, width): - self.width = width - - def __getitem__(self, key): - if isinstance(key, int): - return get_bits(self, self.width, key) - elif isinstance(key, slice): - if key.start != None: - start = key.start - else: - start = 0 - if key.stop != None: - stop = key.stop - else: - stop = self.width - if stop > self.width: - stop = self.width - if key.step != None: - raise KeyError - return get_bits(self, self.width, start, stop) - else: - raise KeyError - - def decode_rle(self): - rle_bit = self[-1] - rle_dat = self[:self.width-1] - - dat = VcdDat(self.width) - i=0 - last = 0 - for d in self: - if rle_bit[i]: - if len(dat) >= 1: - # FIX ME... why is rle_dat in reverse orderd... - for j in range(int(dec2bin(rle_dat[i])[::-1],2)): - dat.append(last) - else: - dat.append(d) - last = d - i +=1 - return dat - -class Var: - def __init__(self, name, width, values=[], type="wire", default="x"): - self.type = type - self.width = width - self.name = name - self.val = default - self.values = values - self.vcd_id = None - - def set_vcd_id(self, s): - self.vcd_id = s - - def __len__(self): - return len(self.values) - - def change(self, cnt): - r = "" - try : - if self.values[cnt+1] != self.val: - r += "b" - r += dec2bin(self.values[cnt+1], self.width)[::-1] - r += " " - r += self.vcd_id - r += "\n" - return r - except : - return r - return r - -class Vcd: - def __init__(self, timescale="1ps", comment=""): - self.timescale = timescale - self.comment = comment - self.vars = [] - self.vcd_id = "!" - self.cnt = -1 - - def add(self, var): - var.set_vcd_id(self.vcd_id) - self.vcd_id = chr(ord(self.vcd_id)+1) - self.vars.append(var) - - def add_from_layout(self, layout, var): - i=0 - for s, n in layout: - self.add(Var(s, n, var[i:i+n])) - i += n - - def __len__(self): - l = 0 - for var in self.vars: - l = max(len(var),l) - return l - - def change(self): - r = "" - c = "" - for var in self.vars: - c += var.change(self.cnt) - if c != "": - r += "#" - r += str(self.cnt+1) - r += "\n" - r += c - return r - - def p_date(self): - now = datetime.datetime.now() - r = "$date\n" - r += "\t" - r += now.strftime("%Y-%m-%d %H:%M") - r += "\n" - r += "$end\n" - return r - - def p_version(self): - r = "$version\n" - r += "\tmiscope VCD dump\n" - r += "$end\n" - return r - - def p_comment(self): - r = "$comment\n" - r += self.comment - r += "\n$end\n" - return r - - def p_timescale(self): - r = "$timescale " - r += self.timescale - r += " $end\n" - return r - - def p_scope(self): - r = "$scope " - r += self.timescale - r += " $end\n" - return r - - def p_vars(self): - r = "" - for var in self.vars: - r += "$var " - r += var.type - r += " " - r += str(var.width) - r += " " - r += var.vcd_id - r += " " - r += var.name - r += " $end\n" - return r - - def p_unscope(self): - r = "$unscope " - r += " $end\n" - return r - - def p_enddefinitions(self): - r = "$enddefinitions " - r += " $end\n" - return r - - def p_dumpvars(self): - r = "$dumpvars\n" - for var in self.vars: - r += "b" - r += dec2bin(var.val, var.width) - r += " " - r += var.vcd_id - r+= "\n" - r += "$end\n" - return r - - def p_valuechange(self): - r = "" - for i in range(len(self)): - r += self.change() - self.cnt += 1 - return r - - def __repr__(self): - r = "" - r += self.p_date() - r += self.p_version() - r += self.p_comment() - r += self.p_timescale() - r += self.p_scope() - r += self.p_vars() - r += self.p_unscope() - r += self.p_enddefinitions() - r += self.p_dumpvars() - r += self.p_valuechange() - return r - - def write(self, filename): - f = open(filename, "w") - f.write(str(self)) - f.close() - -def main(): - myvcd = Vcd() - myvcd.add(Var(1, "foo1", [0,1,0,1,0,1])) - myvcd.add(Var(2, "foo2", [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0])) - myvcd.add(Var(3, "foo3")) - myvcd.add(Var(4, "foo4")) - ramp = [i%128 for i in range(1024)] - myvcd.add(Var(16, "ramp", ramp)) - print(myvcd) - -if __name__ == '__main__': - main() - diff --git a/miscope/trigger.py b/miscope/trigger.py deleted file mode 100644 index 61a9a8d3..00000000 --- a/miscope/trigger.py +++ /dev/null @@ -1,315 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl.specials import Memory -from migen.bus import csr -from migen.bank import description, csrgen -from migen.bank.description import * -from migen.genlib.misc import optree - -from miscope.tools.misc import * - -class RegParams: - def __init__(self, name, base, width, nb): - self.name = name - self.base = base - self.width = width - self.nb = nb - - self.size = nb*width - self.words = int(2**bits_for(self.width-1)/8) - -def list_regs(objects): - r = [] - for object in objects: - if "_reg" in object: - r.append(objects[object]) - return r - -class Term: - # - # Definition - # - def __init__(self, width): - self.width = width - self.interface = None - - self.i = Signal(width) - self.t = Signal(width) - self.m = Signal(width) - self.o = Signal() - - self.reg_p = RegParams("term_reg", 0, width, 2) - self.reg = None - - def get_registers_comb(self): - comb = [self.t.eq(self.reg.storage[0*self.width:1*self.width])] - comb += [self.m.eq(self.reg.storage[1*self.width:2*self.width])] - return comb - - def get_fragment(self): - comb = [self.o.eq((self.m & self.i) == self.t)] - comb += self.get_registers_comb() - return Fragment(comb) - - # - # Driver - # - def set(self, dat, mask=None): - if mask is None: - mask = (2**self.width)-1 - self.interface.write_n(self.reg_p.base, mask, self.width) - self.interface.write_n(self.reg_p.base + self.reg_p.words, dat, self.width) - -class RangeDetector: - # - # Definition - # - def __init__(self, width): - self.width = width - self.pipe = pipe - self.interface = None - - self.reg_p = RegParams("range_reg", 0, width, 2) - self.reg = None - - self.i = Signal(width) - self.low = Signal(width) - self.high = Signal(width) - self.o = Signal() - - def get_registers_comb(self): - comb = [self.low.eq(self.reg.storage[0*self.width:1*self.width])] - comb += [self.low.eq(self.reg.storage[1*self.width:2*self.width])] - return comb - - def get_fragment(self): - comb = [self.o.eq((self.i >= self.low) & (self.i <= self.high))] - comb += self.get_registers_comb() - return Fragment(comb) - # - # Driver - # - def set_low(self, dat): - self.interface.write_n(self.reg_p.base, dat ,self.width) - - def set_high(self, dat): - self.interface.write_n(self.reg_p.base + self.reg_p.words, dat ,self.width) - -class EdgeDetector: - # - # Definition - # - def __init__(self, width, mode="RFB"): - self.width = width - self.mode = mode - self.interface = None - - self.reg_p = RegParams("edge_reg", 0, width, len(self.mode)) - self.reg = None - - self.i = Signal(self.width) - self.i_d = Signal(self.width) - if "R" in self.mode: - self.r_mask = Signal(self.width) - self.ro = Signal() - if "F" in self.mode: - self.f_mask = Signal(self.width) - self.fo = Signal() - if "B" in self.mode: - self.b_mask = Signal(self.width) - self.bo = Signal() - self.o = Signal() - - def get_registers_comb(self): - comb = [] - i = 0 - if "R" in self.mode: - comb += [self.r_mask.eq(self.reg.storage[i*self.width:(i+1)*self.width])] - i += 1 - if "F" in self.mode: - comb += [self.f_mask.eq(self.reg.storage[i*self.width:(i+1)*self.width])] - i += 1 - if "B" in self.mode: - comb += [self.b_mask.eq(self.reg.storage[i*self.width:(i+1)*self.width])] - i += 1 - return comb - - def get_fragment(self): - comb = [] - sync = [self.i_d.eq(self.i)] - - # Rising Edge - if "R" in self.mode: - comb += [self.ro.eq(self.r_mask & self.i & (~self.i_d))] - else: - comb += [self.ro.eq(0)] - - # Falling Edge - if "F" in self.mode: - comb += [self.fo.eq(self.f_mask & (~self.i) & self.i_d)] - else: - comb += [self.fo.eq(0)] - - # Both - if "B" in self.mode: - comb += [self.bo.eq((self.b_mask & self.i) != self.i_d)] - else: - comb += [self.bo.eq(0)] - - # Output - comb += [self.o.eq(self.ro | self.fo | self.bo)] - - # Registers - comb += self.get_registers_comb() - - return Fragment(comb, sync) - - # - # Driver - # - def get_offset(self, type): - if type == "R": - r = 0 - r = r + self.words if "F" in self.mode else r - r = r + self.words if "B" in self.mode else r - return r - elif type == "F": - r = 0 - r = r + self.words if "B" in self.mode else r - return r - elif type == "B": - r = 0 - return r - return 0 - - def set_r(self, dat): - self.interface.write_n(self.reg_p.base + self.get_offset("R"), dat ,self.width) - - def set_f(self, dat): - self.interface.write_n(self.reg_p.base + self.get_offset("F"), dat ,self.width) - - def set_b(self, dat): - self.interface.write_n(self.reg_p.base + self.get_offset("B"), dat ,self.width) - -class Sum: - # - # Definition - # - def __init__(self, width=4): - self.width = width - self.interface = None - - self.i = Signal(self.width) - self.o = Signal() - - self.reg_p = RegParams("sum_reg", 0, 8, 4) - self.reg = None - - self.prog_stb = Signal() - self.prog_adr = Signal(width) - self.prog_dat = Signal() - - self._mem = Memory(1, 2**self.width) - self._lut_port = self._mem.get_port() - self._prog_port = self._mem.get_port(write_capable=True) - - def get_registers_comb(self): - comb = [ - self.prog_adr.eq(self.reg.storage[0:16]), - self.prog_dat.eq(self.reg.storage[16]), - self.prog_stb.eq(self.reg.storage[17]) - ] - return comb - - def get_fragment(self): - comb = [ - self._lut_port.adr.eq(self.i), - - self._prog_port.adr.eq(self.prog_adr), - self._prog_port.we.eq(self.prog_stb), - self._prog_port.dat_w.eq(self.prog_dat), - - self.o.eq(self._lut_port.dat_r), - ] - comb += self.get_registers_comb() - return Fragment(comb, specials={self._mem}) - - # - # Driver - # - def set(self, truth_table): - for i in range(len(truth_table)): - val = truth_table[i] - we = 1<<17 - dat = val<<16 - addr = i - self.interface.write_n(self.reg_p.base, we + dat + addr, self.reg_p.size) - self.interface.write_n(self.reg_p.base, dat + addr, self.reg_p.size) - -class Trigger: - # - # Definition - # - def __init__(self, width, ports, address=0x0000, interface=None): - self.width = width - self.ports = ports - - self.sum = Sum(len(ports)) - self.trig = Signal(self.width) - self.hit = Signal() - - # insert port number in port reg name - for i in range(len(self.ports)): - self.ports[i].reg_p.name += "_%d"%i - - # generate ports csr registers fields - for port in self.ports: - rf = CSRStorage(port.reg_p.size, reset=0, name=port.reg_p.name) - setattr(self, port.reg_p.name, rf) - - # generate sum csr registers fields - self.sum_reg = CSRStorage(self.sum.reg_p.size, reset=0, name=self.sum.reg_p.name) - - # generate registers - self.regs = list_regs(self.__dict__) - self.bank = csrgen.Bank(self.regs, address=address) - - # update base addr & interface - self.set_address(address) - self.set_interface(interface) - self.set_registers() - - def set_address(self, address): - self.address = address - self.bank = csrgen.Bank(self.regs, address=self.address) - for port in self.ports: - port.reg_p.base = get_csr_base(self.bank, port.reg_p.name) - self.sum.reg_p.base = get_csr_base(self.bank, self.sum.reg_p.name) - - def set_interface(self, interface): - self.interface = interface - for port in self.ports: - port.interface = self.interface - self.sum.interface = self.interface - - def set_registers(self): - self.sum.reg=self.sum_reg - for port in self.ports: - port.reg=getattr(self, port.reg_p.name) - - def get_fragment(self): - # connect trig to input of each trig element - comb = [port.i.eq(self.trig) for port in self.ports] - - # connect output of trig elements to sum - comb += [self.sum.i[j].eq(self.ports[j].o) for j in range(len(self.ports))] - - # connect sum ouput to hit - comb += [self.hit.eq(self.sum.o)] - - # add ports & sum to frag - frag = self.bank.get_fragment() - frag += self.sum.get_fragment() - for port in self.ports: - frag += port.get_fragment() - - return frag + Fragment(comb) diff --git a/miscope/triggering/__init__.py b/miscope/triggering/__init__.py new file mode 100644 index 00000000..3a328ae8 --- /dev/null +++ b/miscope/triggering/__init__.py @@ -0,0 +1,95 @@ +from migen.fhdl.std import * +from migen.flow.actor import * +from migen.flow.network import * +from migen.fhdl.specials import Memory +from migen.bus import csr +from migen.bank import description, csrgen +from migen.bank.description import * + +class Term(Module, AutoCSR): + def __init__(self, width): + self.width = width + + self.sink = Sink([("d", width)]) + self.source = Source([("hit", 1)]) + + self.busy = Signal() + + self._r_trig = CSRStorage(width) + self._r_mask = CSRStorage(width) + + ### + + trig = self._r_trig.storage + mask = self._r_mask.storage + + hit = Signal() + + self.comb +=[ + hit.eq((self.sink.payload.d & mask) == trig), + self.source.stb.eq(self.sink.stb), + self.sink.ack.eq(self.sink.ack), + self.source.payload.hit.eq(hit) + ] + +class Sum(Module, AutoCSR): + def __init__(self, ports=4): + + self.sinks = [Sink([("hit", 1)]) for p in range(ports)] + self.source = Source([("hit", 1)]) + + self._r_prog_we = CSRStorage() + self._r_prog_adr = CSRStorage(ports) #FIXME + self._r_prog_dat = CSRStorage() + + mem = Memory(1, 2**ports) + lut_port = mem.get_port() + prog_port = mem.get_port(write_capable=True) + + self.specials += mem, lut_port, prog_port + + ### + + # Lut prog + self.comb +=[ + prog_port.we.eq(self._r_prog_we.storage), + prog_port.adr.eq(self._r_prog_adr.storage), + prog_port.dat_w.eq(self._r_prog_dat.storage) + ] + + # Lut read + for i, sink in enumerate(self.sinks): + self.comb += lut_port.adr[i].eq(sink.payload.hit) + + # Drive source + self.comb +=[ + self.source.stb.eq(optree("&", [sink.stb for sink in self.sinks])), + self.source.payload.hit.eq(lut_port.dat_r), + [sink.ack.eq(self.source.ack) for sink in self.sinks] + ] + + +class Trigger(Module, AutoCSR): + def __init__(self, width, ports): + self.width = width + self.ports = ports + + self.submodules.sum = Sum(len(ports)) + + # FIXME : when self.submodules += is used, + # get_csrs() is not called + for i, port in enumerate(ports): + tmp = "self.submodules.port"+str(i)+" = port" + exec(tmp) + + self.sink = Sink([("d", width)]) + self.source = self.sum.source + self.busy = Signal() + + ### + for i, port in enumerate(ports): + self.comb +=[ + port.sink.stb.eq(self.sink.stb), + port.sink.payload.d.eq(self.sink.payload.d), + port.source.connect(self.sum.sinks[i]) + ] \ No newline at end of file diff --git a/sim/tb_RecorderCsr.py b/sim/tb_RecorderCsr.py deleted file mode 100644 index 9aaf3d01..00000000 --- a/sim/tb_RecorderCsr.py +++ /dev/null @@ -1,111 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog -from migen.bus import csr -from migen.sim.generic import Simulator, PureSimulable, TopLevel -from migen.sim.icarus import Runner -from migen.bus.transactions import * - -from miscope.recorder import * - -arm_done = False -dat = 0 - -rec_done = False - -dat_rdy = False - -rec_size = 128 - -def csr_transactions(): - - # Reset - yield TWrite(REC_RST_BASE, 1) - yield TWrite(REC_RST_BASE, 0) - - # RLE - yield TWrite(REC_RLE_BASE, 1) - - # Size - yield TWrite(REC_SIZE_BASE + 0, 0) - yield TWrite(REC_SIZE_BASE + 1, rec_size) - - # Offset - yield TWrite(REC_OFFSET_BASE + 0, 0) - yield TWrite(REC_OFFSET_BASE + 1, 0) - - # Arm - yield TWrite(REC_ARM_BASE, 1) - yield TWrite(REC_ARM_BASE, 0) - - for t in range(10): - yield None - - global arm_done - arm_done = True - - global rec_done - while not rec_done: - yield None - - global dat_rdy - for t in range(rec_size): - yield TWrite(REC_READ_BASE, 1) - dat_rdy = False - yield TWrite(REC_READ_BASE, 0) - yield TRead(REC_READ_DATA_BASE + 0) - yield TRead(REC_READ_DATA_BASE + 1) - yield TRead(REC_READ_DATA_BASE + 2) - yield TRead(REC_READ_DATA_BASE + 3) - dat_rdy = True - - dat_rdy = False - - for t in range(100): - yield None - -def main(): - # Csr Master - csr_master0 = csr.Initiator(csr_transactions()) - - # Recorder - recorder0 = Recorder(32, 1024) - - # Csr Interconnect - csrcon0 = csr.Interconnect(csr_master0.bus, - [ - recorder0.bank.bus - ]) - - # Recorder Data - def recorder_data(s): - global arm_done - if arm_done: - s.wr(recorder0.hit, 1) - arm_done = False - - global dat - s.wr(recorder0.dat, dat//5) - dat += 1 - - global rec_done - if s.rd(recorder0.sequencer.enable) == 0: - rec_done = True - - if dat_rdy: - print("%08X" %s.rd(recorder0._pull_dat.field.w)) - - # Simulation - def end_simulation(s): - s.interrupt = csr_master0.done - - fragment = csr_master0.get_fragment() - fragment += recorder0.get_fragment() - fragment += csrcon0.get_fragment() - fragment += Fragment(sim=[end_simulation]) - fragment += Fragment(sim=[recorder_data]) - sim = Simulator(fragment, TopLevel("tb_RecorderCsr.vcd")) - sim.run(10000) - -main() -print("Sim Done") -input() \ No newline at end of file diff --git a/sim/tb_TriggerCsr.py b/sim/tb_TriggerCsr.py deleted file mode 100644 index 9262872e..00000000 --- a/sim/tb_TriggerCsr.py +++ /dev/null @@ -1,114 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog -from migen.bus import csr -from migen.sim.generic import Simulator, PureSimulable, TopLevel -from migen.sim.icarus import Runner -from migen.bus.transactions import * - -from miscope import trigger -from miscope.tools.truthtable import * - -def term_prog(off, dat): - for i in range(4): - yield TWrite(off+3-i, (dat>>(8*i))&0xFF) - -def sum_prog(off, addr, dat): - we = 2 - yield TWrite(off+3, addr%0xFF) - yield TWrite(off+2, (addr>>8)%0xFF) - yield TWrite(off+1, we+dat) - yield TWrite(off+0, 0) - for i in range(4): - yield TWrite(off+i,0) - - -csr_done = False - -def csr_transactions(): - - term_trans = [] - term_trans += [term_prog(0x04+0 ,0xFFFFFFFF)] - term_trans += [term_prog(0x04+4 ,0xDEADBEEF)] - term_trans += [term_prog(0x04+8 ,0xFFFFFFFF)] - term_trans += [term_prog(0x04+12 ,0xCAFEFADE)] - term_trans += [term_prog(0x04+16 ,0xFFFFFFFF)] - term_trans += [term_prog(0x04+20 ,0xDEADBEEF)] - term_trans += [term_prog(0x04+24 ,0xFFFFFFFF)] - term_trans += [term_prog(0x04+28 ,0xCAFEFADE)] - for t in term_trans: - for r in t: - yield r - - sum_trans = [] - sum_trans += [sum_prog(0x00, i, 1) for i in range(8)] - sum_trans += [sum_prog(0x00, i, 0) for i in range(8)] - for t in sum_trans: - for r in t: - yield r - - sum_tt = gen_truth_table("i1 & i2 & i3 & i4") - sum_trans = [] - for i in range(len(sum_tt)): - sum_trans.append(sum_prog(0x00, i, sum_tt[i])) - print(sum_tt) - for t in sum_trans: - for r in t: - yield r - - global csr_done - csr_done = True - - for t in range(100): - yield None - - -def main(): - # Csr Master - csr_master0 = csr.Initiator(csr_transactions()) - - # Trigger - term0 = trigger.Term(32) - term1 = trigger.Term(32) - term2 = trigger.Term(32) - term3 = trigger.Term(32) - trigger0 = trigger.Trigger(32, [term0, term1, term2, term3]) - - # Csr Interconnect - csrcon0 = csr.Interconnect(csr_master0.bus, - [ - trigger0.bank.bus - ]) - - # Term Test - def term_stimuli(s): - if csr_done: - s.wr(term0.i, 0xDEADBEEF) - s.wr(term1.i ,0xCAFEFADE) - s.wr(term2.i, 0xDEADBEEF) - s.wr(term3.i, 0xCAFEFADE) - - - # Simulation - def end_simulation(s): - s.interrupt = csr_master0.done - - fragment = csr_master0.get_fragment() - fragment += term0.get_fragment() - fragment += term1.get_fragment() - fragment += term2.get_fragment() - fragment += term3.get_fragment() - fragment += trigger0.get_fragment() - fragment += csrcon0.get_fragment() - fragment += Fragment(sim=[end_simulation]) - fragment += Fragment(sim=[term_stimuli]) - sim = Simulator(fragment, TopLevel("tb_TriggerCsr.vcd")) - sim.run(2000) - -main() -print("Sim Done") -input() - - - - - diff --git a/sim/tb_miscope.py b/sim/tb_miscope.py deleted file mode 100644 index 5b2107d8..00000000 --- a/sim/tb_miscope.py +++ /dev/null @@ -1,192 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog -from migen.bus import csr -from migen.sim.generic import Simulator, PureSimulable, TopLevel -from migen.sim.icarus import Runner -from migen.bus.transactions import * - -from miscope.trigger import * -from miscope.recorder import * -from miscope.tools.truthtable import * -from miscope.tools.vcd import * - -TRIGGER_ADDR = 0x0000 -RECORDER_ADDR = 0x0200 - -rec_done = False -dat_rdy = False - -dat_vcd = VcdDat(32) -rec_size = 64 - -def term_prog(off, dat): - for i in range(4): - yield TWrite(off+3-i, (dat>>(8*i))&0xFF) - - -def sum_prog(off, addr, dat): - we = 2 - yield TWrite(off+3, addr%0xFF) - yield TWrite(off+2, (addr>>8)%0xFF) - yield TWrite(off+1, we+dat) - yield TWrite(off+0, 0) - for i in range(4): - yield TWrite(off+i,0) - -def csr_transactions(trigger0, recorder0): - - # Trigger Prog - ############################## - - # Term Prog - term_trans = [] - term_trans += [term_prog(trigger0.ports[0].reg_p.base+0, 0xFFFFFFFF)] - term_trans += [term_prog(trigger0.ports[0].reg_p.base+4, 0x00000000)] - term_trans += [term_prog(trigger0.ports[1].reg_p.base+0, 0xFFFFFFFF)] - term_trans += [term_prog(trigger0.ports[1].reg_p.base+4, 0x00000004)] - term_trans += [term_prog(trigger0.ports[2].reg_p.base+0, 0xFFFFFFFF)] - term_trans += [term_prog(trigger0.ports[2].reg_p.base+4, 0x00000008)] - term_trans += [term_prog(trigger0.ports[3].reg_p.base+0, 0xFFFFFFFF)] - term_trans += [term_prog(trigger0.ports[3].reg_p.base+4, 0x0000000C)] - for t in term_trans: - for r in t: - yield r - - # Sum Prog - sum_tt = gen_truth_table("term0 | term1 | term2 | term3") - sum_trans = [] - for i in range(len(sum_tt)): - sum_trans.append(sum_prog(trigger0.sum.reg_p.base, i, sum_tt[i])) - for t in sum_trans: - for r in t: - yield r - - # Recorder Prog - ############################## - #Reset - yield TWrite(recorder0.address + REC_RST_BASE, 1) - yield TWrite(recorder0.address + REC_RST_BASE, 0) - - # RLE - yield TWrite(REC_RLE_BASE, 0) - - #Size - yield TWrite(recorder0.address + REC_SIZE_BASE + 0, 0) - yield TWrite(recorder0.address + REC_OFFSET_BASE + 1, rec_size) - - #Offset - yield TWrite(recorder0.address + REC_OFFSET_BASE + 0, 0) - yield TWrite(recorder0.address + REC_OFFSET_BASE + 1, 16) - - #Arm - yield TWrite(recorder0.address + REC_ARM_BASE, 1) - yield TWrite(recorder0.address + REC_ARM_BASE, 0) - - # Wait Record to be done - ############################## - global rec_done - while not rec_done: - yield None - - # Read recorded data - ############################## - global dat_rdy - for t in range(rec_size): - yield TWrite(recorder0.address + REC_READ_BASE, 1) - dat_rdy = False - yield TWrite(recorder0.address + REC_READ_BASE, 0) - yield TRead(recorder0.address + REC_READ_DATA_BASE + 0) - yield TRead(recorder0.address + REC_READ_DATA_BASE + 1) - yield TRead(recorder0.address + REC_READ_DATA_BASE + 2) - yield TRead(recorder0.address + REC_READ_DATA_BASE + 3) - dat_rdy = True - - dat_rdy = False - - for t in range(512): - yield None - - -trig_sig_val = 0 - - -def main(): - - # Trigger - term0 = Term(32) - term1 = Term(32) - term2 = Term(32) - term3 = Term(32) - trigger0 = Trigger(32, [term0, term1, term2, term3], address=TRIGGER_ADDR) - - # Recorder - recorder0 = Recorder(32, 1024, address=RECORDER_ADDR) - - # Csr Master - csr_master0 = csr.Initiator(csr_transactions(trigger0, recorder0)) - - # Csr Interconnect - csrcon0 = csr.Interconnect(csr_master0.bus, - [ - trigger0.bank.bus, - recorder0.bank.bus - ]) - - trig_sig = Signal(32) - comb =[ - trigger0.trig.eq(trig_sig) - ] - - comb += [ - recorder0.dat.eq(trig_sig), - recorder0.hit.eq(trigger0.hit) - ] - # Term Test - def term_stimuli(s): - global trig_sig_val - s.wr(trig_sig,trig_sig_val) - trig_sig_val += 1 - trig_sig_val = trig_sig_val % 256 - - # Recorder Data - def recorder_data(s): - global rec_done - if s.rd(recorder0.sequencer.done) == 1: - rec_done = True - - global dat_rdy - if dat_rdy: - print("%08X" %s.rd(recorder0._pull_dat.field.w)) - global dat_vcd - dat_vcd.append(s.rd(recorder0._pull_dat.field.w)) - - - # Simulation - def end_simulation(s): - s.interrupt = csr_master0.done - myvcd = Vcd() - myvcd.add(Var("trig_dat", 32, dat_vcd)) - f = open("tb_miscope_out.vcd", "w") - f.write(str(myvcd)) - f.close() - - fragment = term0.get_fragment() - fragment += term1.get_fragment() - fragment += term2.get_fragment() - fragment += term3.get_fragment() - fragment += trigger0.get_fragment() - fragment += recorder0.get_fragment() - fragment += csr_master0.get_fragment() - fragment += csrcon0.get_fragment() - - fragment += Fragment(comb=comb) - fragment += Fragment(sim=[term_stimuli]) - fragment += Fragment(sim=[recorder_data]) - fragment += Fragment(sim=[end_simulation]) - - sim = Simulator(fragment, TopLevel("tb_miscope.vcd")) - sim.run(2000) - -main() -print("Sim Done") -input() diff --git a/sim/tb_recorder_csr.py b/sim/tb_recorder_csr.py new file mode 100644 index 00000000..a14eba00 --- /dev/null +++ b/sim/tb_recorder_csr.py @@ -0,0 +1,142 @@ +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.bus.transactions import * + +from miscope.recording import * +from miscope.std.truthtable import * + +from miscope.std import cif + +from mibuild.tools import write_to_file + +try: + from csr_header import * + print("csr_header imported") +except: + print("csr_header not found") + +class Csr2Trans(): + def __init__(self): + self.t = [] + + def write_csr(self, adr, value): + self.t.append(TWrite(adr//4, value)) + + def read_csr(self, adr): + self.t.append(TRead(adr//4)) + return 0 + + +triggered = False +dat = 0 + +rec_done = False + +dat_rdy = False + +rec_length = 128 + +def csr_configure(): + bus = Csr2Trans() + + # Length + recorder_length_write(bus, rec_length) + + # Offset + recorder_offset_write(bus, 0) + + # Trigger + recorder_trigger_write(bus, 1) + + return bus.t + +def csr_read_data(): + bus = Csr2Trans() + + for i in range(rec_length+100): + recorder_read_dat_read(bus) + recorder_read_en_write(bus, 1) + return bus.t + +def csr_transactions(): + for t in csr_configure(): + yield t + + for t in range(100): + yield None + + global triggered + triggered = True + + for t in range(512): + yield None + + for t in csr_read_data(): + yield t + + for t in range(100): + yield None + + +class TB(Module): + csr_base = 0 + csr_map = { + "recorder": 1, + } + def __init__(self, first_run=False): + 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()) + + # Recorder Data + def recorder_data(self, s): + s.wr(self.recorder.sink.stb, 1) + if not hasattr(self, "cnt"): + self.cnt = 0 + self.cnt += 1 + + s.wr(self.recorder.sink.payload.d, self.cnt) + + global triggered + if triggered: + s.wr(self.recorder.sink.payload.hit, 1) + triggered = False + else: + s.wr(self.recorder.sink.payload.hit, 0) + + # Simulation + def end_simulation(self, s): + s.interrupt = self.master.done + + + def do_simulation(self, s): + self.recorder_data(s) + self.end_simulation(s) + + +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) + print("Sim Done") + input() + +main() \ No newline at end of file diff --git a/sim/tb_spi2csr.py b/sim/tb_spi2csr.py deleted file mode 100644 index ecc58e45..00000000 --- a/sim/tb_spi2csr.py +++ /dev/null @@ -1,168 +0,0 @@ -from migen.fhdl.structure import * -from migen.fhdl import verilog, autofragment -from migen.bus import csr -from migen.sim.generic import Simulator, PureSimulable, TopLevel -from migen.sim.icarus import Runner -from migen.bus.transactions import * -from migen.bank import description, csrgen -from migen.bank.description import * - -import miscope.bridges.spi2csr - -def get_bit(dat, bit): - return int(dat & (1<= a_w*self.clk_ratio and self.transaction_cnt < (a_w + d_w)*self.clk_ratio: - bit = d_w-1-int((self.transaction_cnt-a_w*self.clk_ratio)/self.clk_ratio) - data = get_bit(self.transaction.data,bit) - s.wr(self.spi.spi_mosi, data) - else: - s.wr(self.spi.spi_mosi, 0) - - # Cs_n - if self.transaction_cnt < (a_w + d_w)*self.clk_ratio: - s.wr(self.spi.spi_cs_n,0) - else: - s.wr(self.spi.spi_cs_n, 1) - s.wr(self.spi.spi_clk, 0) - s.wr(self.spi.spi_mosi, 0) - self.transaction = None - - # Incr transaction_cnt - self.transaction_cnt +=1 - - elif isinstance(self.transaction, TRead): - - # Clk - if (int(self.transaction_cnt/(self.clk_ratio/2)))%2: - s.wr(self.spi.spi_clk, 1) - else: - s.wr(self.spi.spi_clk, 0) - - # Mosi Addr - if self.transaction_cnt < a_w*self.clk_ratio: - bit = a_w-1-int((self.transaction_cnt)/self.clk_ratio) - if int(self.transaction_cnt/self.clk_ratio) == 0: - data = 0 - else: - data = get_bit(self.transaction.address, bit) - s.wr(self.spi.spi_mosi, data) - else: - s.wr(self.spi.spi_mosi, 0) - - # Miso Data - if self.transaction_cnt >= a_w*self.clk_ratio and self.transaction_cnt%self.clk_ratio==self.clk_ratio/2: - bit = d_w-1-int((self.transaction_cnt-a_w*self.clk_ratio)/self.clk_ratio) - if s.rd(self.spi.spi_miso): - self.r_dat = set_bit(self.r_dat, bit) - - # Cs_n - if self.transaction_cnt < (a_w + d_w)*self.clk_ratio: - s.wr(self.spi.spi_cs_n,0) - else: - s.wr(self.spi.spi_cs_n, 1) - s.wr(self.spi.spi_clk, 0) - s.wr(self.spi.spi_mosi, 0) - self.transaction = None - print("%02X" %self.r_dat) - - # Incr transaction_cnt - self.transaction_cnt +=1 - - -def main(): - # Csr Slave - scratch_reg0 = RegisterField("scratch_reg0", 32, reset=0, access_dev=READ_ONLY) - scratch_reg1 = RegisterField("scratch_reg1", 32, reset=0, access_dev=READ_ONLY) - scratch_reg2 = RegisterField("scratch_reg3", 32, reset=0, access_dev=READ_ONLY) - scratch_reg3 = RegisterField("scratch_reg4", 32, reset=0, access_dev=READ_ONLY) - regs = [scratch_reg0, scratch_reg1, scratch_reg2, scratch_reg3] - bank0 = csrgen.Bank(regs,address=0x0000) - - # Spi2Csr - spi2csr0 = spi2csr.Spi2Csr(16,8) - - - # Csr Interconnect - csrcon0 = csr.Interconnect(spi2csr0.csr, - [ - bank0.interface - ]) - - # Spi Master - spi_master0 = SpiMaster(spi2csr0, 8, spi_transactions()) - - # Simulation - def end_simulation(s): - s.interrupt = spi_master0.done - - - fragment = autofragment.from_local() - fragment += Fragment(sim=[end_simulation]) - sim = Simulator(fragment, Runner(),TopLevel("tb_spi2Csr.vcd")) - sim.run(10000) - -main() -input() diff --git a/sim/tb_trigger_csr.py b/sim/tb_trigger_csr.py new file mode 100644 index 00000000..d2be9214 --- /dev/null +++ b/sim/tb_trigger_csr.py @@ -0,0 +1,109 @@ +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.bus.transactions import * + +from miscope.triggering import * +from miscope.std.truthtable import * + +from miscope.std import cif + +from mibuild.tools import write_to_file + +try: + from csr_header import * + print("csr_header imported") +except: + print("csr_header not found") + +class Csr2Trans(): + def __init__(self): + self.t = [] + + def write_csr(self, adr, value): + self.t.append(TWrite(adr//4, value)) + + 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) + + 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) + + return bus.t + + +csr_done = False + +def csr_transactions(): + for t in csr_prog_mila(): + yield t + global csr_done + csr_done = True + for t in range(100): + yield None + +class TB(Module): + csr_base = 0 + csr_map = { + "trigger": 1, + } + def __init__(self, first_run=False): + + + # Csr Master + if not first_run: + self.submodules.master = csr.Initiator(csr_transactions()) + + # Trigger + term0 = Term(32) + term1 = Term(32) + term2 = Term(32) + term3 = Term(32) + self.submodules.trigger = Trigger(32, [term0, term1, term2, term3]) + + # 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()) + + self.terms = [term0, term1, term2, term3] + + def do_simulation(self, s): + for term in self.terms: + s.wr(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 + +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) + print("Sim Done") + input() + +main()