From ce9bff21e9c02e5292d12313c27591730b1350d8 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 21 Sep 2013 13:04:07 +0200 Subject: [PATCH] refactoring --- examples/de0_nano/Makefile | 9 +- examples/de0_nano/build.py | 22 -- examples/de0_nano/client/test_miio.py | 32 +- examples/de0_nano/client/test_mila.py | 85 +++-- examples/de0_nano/make.py | 42 +++ examples/de0_nano/top.py | 48 +-- miscope/bridges/spi2csr/__init__.py | 135 -------- .../bridges/spi2csr/tools/arduino/spiFpga.cpp | 59 ---- .../bridges/spi2csr/tools/arduino/spiFpga.h | 28 -- .../spi2csr/tools/arduino/uart2Spi.pde | 51 --- miscope/bridges/spi2csr/tools/uart2Spi.py | 56 --- miscope/{bridges => com}/__init__.py | 0 miscope/{bridges => com}/uart2csr/__init__.py | 67 ++-- .../tools => com/uart2csr/host}/__init__.py | 0 .../uart2csr/host/uart2csr.py} | 15 +- miscope/{bridges => com}/uart2csr/uart.py | 0 miscope/miio.py | 53 +-- miscope/mila.py | 53 +-- miscope/recorder.py | 324 ------------------ miscope/recording/__init__.py | 86 +++++ .../uart2csr/tools => std}/__init__.py | 0 miscope/std/cif.py | 94 +++++ miscope/{tools => std}/conv.py | 0 {examples/de0_nano => miscope/std}/misc.py | 21 +- miscope/{tools => std}/truthtable.py | 0 miscope/{tools => std}/vcd.py | 0 miscope/tools/__init__.py | 0 miscope/tools/misc.py | 123 ------- miscope/trigger.py | 315 ----------------- miscope/triggering/__init__.py | 95 +++++ sim/tb_RecorderCsr.py | 111 ------ sim/tb_TriggerCsr.py | 114 ------ sim/tb_miscope.py | 192 ----------- sim/tb_recorder_csr.py | 142 ++++++++ sim/tb_spi2csr.py | 168 --------- sim/tb_trigger_csr.py | 109 ++++++ 36 files changed, 753 insertions(+), 1896 deletions(-) delete mode 100644 examples/de0_nano/build.py create mode 100644 examples/de0_nano/make.py delete mode 100644 miscope/bridges/spi2csr/__init__.py delete mode 100644 miscope/bridges/spi2csr/tools/arduino/spiFpga.cpp delete mode 100644 miscope/bridges/spi2csr/tools/arduino/spiFpga.h delete mode 100644 miscope/bridges/spi2csr/tools/arduino/uart2Spi.pde delete mode 100644 miscope/bridges/spi2csr/tools/uart2Spi.py rename miscope/{bridges => com}/__init__.py (100%) rename miscope/{bridges => com}/uart2csr/__init__.py (60%) rename miscope/{bridges/spi2csr/tools => com/uart2csr/host}/__init__.py (100%) rename miscope/{bridges/uart2csr/tools/uart2Csr.py => com/uart2csr/host/uart2csr.py} (89%) rename miscope/{bridges => com}/uart2csr/uart.py (100%) delete mode 100644 miscope/recorder.py create mode 100644 miscope/recording/__init__.py rename miscope/{bridges/uart2csr/tools => std}/__init__.py (100%) create mode 100644 miscope/std/cif.py rename miscope/{tools => std}/conv.py (100%) rename {examples/de0_nano => miscope/std}/misc.py (86%) rename miscope/{tools => std}/truthtable.py (100%) rename miscope/{tools => std}/vcd.py (100%) delete mode 100644 miscope/tools/__init__.py delete mode 100644 miscope/tools/misc.py delete mode 100644 miscope/trigger.py create mode 100644 miscope/triggering/__init__.py delete mode 100644 sim/tb_RecorderCsr.py delete mode 100644 sim/tb_TriggerCsr.py delete mode 100644 sim/tb_miscope.py create mode 100644 sim/tb_recorder_csr.py delete mode 100644 sim/tb_spi2csr.py create mode 100644 sim/tb_trigger_csr.py 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/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/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/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/__init__.py b/miscope/com/__init__.py similarity index 100% rename from miscope/bridges/__init__.py rename to miscope/com/__init__.py diff --git a/miscope/bridges/uart2csr/__init__.py b/miscope/com/uart2csr/__init__.py similarity index 60% rename from miscope/bridges/uart2csr/__init__.py rename to miscope/com/uart2csr/__init__.py index a9c20fa6..e8e569ce 100644 --- a/miscope/bridges/uart2csr/__init__.py +++ b/miscope/com/uart2csr/__init__.py @@ -1,9 +1,9 @@ from migen.fhdl.structure import * from migen.fhdl.module import * from migen.bus import csr -from migen.genlib.fsm import * +from migen.genlib.fsm import FSM, NextState -from miscope.bridges.uart2csr.uart import * +from miscope.com.uart2csr.uart import * WRITE_CMD = 0x01 READ_CMD = 0x02 @@ -39,10 +39,7 @@ class Uart2Csr(Module): data = Signal(8) # FSM - self.submodules.fsm = FSM("IDLE", - "GET_BL", "GET_ADDR", - "GET_DATA", "WRITE_CSR", - "READ_CSR0", "READ_CSR1", "SEND_DATA") + self.submodules.fsm = FSM(reset_state="IDLE") fsm = self.fsm @@ -50,7 +47,7 @@ class Uart2Csr(Module): # Global # self.sync +=[ - If(fsm.ongoing(fsm.IDLE), cnt.eq(0) + 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]))) @@ -66,45 +63,45 @@ class Uart2Csr(Module): # # Idle # - fsm.act(fsm.IDLE, + fsm.act("IDLE", If(uart.rx_ev & ((uart.rx_dat == WRITE_CMD) | (uart.rx_dat == READ_CMD)), - fsm.next_state(fsm.GET_BL) + NextState("GET_BL") ) ) - self.sync += If(fsm.ongoing(fsm.IDLE) & uart.rx_ev, cmd.eq(uart.rx_dat)) + self.sync += If(fsm.ongoing("IDLE") & uart.rx_ev, cmd.eq(uart.rx_dat)) # # Get burst length # - fsm.act(fsm.GET_BL, + fsm.act("GET_BL", If(get_bl_done, - fsm.next_state(fsm.GET_ADDR) + NextState("GET_ADDR") ) ) - self.comb += get_bl_done.eq(uart.rx_ev & fsm.ongoing(fsm.GET_BL)) + 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(fsm.GET_ADDR, + fsm.act("GET_ADDR", If(get_addr_done & (cmd == WRITE_CMD), - fsm.next_state(fsm.GET_DATA) + NextState("GET_DATA") ).Elif(get_addr_done & (cmd == READ_CMD), - fsm.next_state(fsm.READ_CSR0) + NextState("READ_CSR0") ) ) - self.comb += get_addr_done.eq(uart.rx_ev & (cnt == 4) & fsm.ongoing(fsm.GET_ADDR)) + 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(fsm.WRITE_CSR) | send_data_done, + ).Elif(fsm.leaving("WRITE_CSR") | send_data_done, addr.eq(addr + 1) ) ] @@ -112,13 +109,13 @@ class Uart2Csr(Module): # # Get data # - fsm.act(fsm.GET_DATA, + fsm.act("GET_DATA", If(get_data_done, - fsm.next_state(fsm.WRITE_CSR) + NextState("WRITE_CSR") ) ) - self.comb += get_data_done.eq(uart.rx_ev & fsm.ongoing(fsm.GET_DATA)) + 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), @@ -129,46 +126,46 @@ class Uart2Csr(Module): # # Write Csr # - fsm.act(fsm.WRITE_CSR, + fsm.act("WRITE_CSR", If((burst_cnt==0), - fsm.next_state(fsm.IDLE) - ).Else(fsm.next_state(fsm.GET_DATA)) + NextState("IDLE") + ).Else(NextState("GET_DATA")) ) # # Read Csr0 # - fsm.act(fsm.READ_CSR0, - fsm.next_state(fsm.READ_CSR1) + fsm.act("READ_CSR0", + NextState("READ_CSR1") ) - self.sync += If(fsm.entering(fsm.READ_CSR0), burst_cnt.eq(burst_cnt-1)) + self.sync += If(fsm.entering("READ_CSR0"), burst_cnt.eq(burst_cnt-1)) # # Read Csr1 # - fsm.act(fsm.READ_CSR1, - fsm.next_state(fsm.SEND_DATA) + fsm.act("READ_CSR1", + NextState("SEND_DATA") ) # # Send Data # - fsm.act(fsm.SEND_DATA, + fsm.act("SEND_DATA", If(send_data_done & (burst_cnt==0), - fsm.next_state(fsm.IDLE) + NextState("IDLE") ).Elif(send_data_done, - fsm.next_state(fsm.READ_CSR0) + NextState("READ_CSR0") ) ) - self.comb += send_data_done.eq(fsm.ongoing(fsm.SEND_DATA) & uart.tx_ev) + 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(fsm.SEND_DATA)), + uart.tx_we.eq(fsm.entering("SEND_DATA")), ] @@ -178,7 +175,7 @@ class Uart2Csr(Module): self.comb += self.csr.adr.eq(addr) self.sync +=[ self.csr.dat_w.eq(data), - If(fsm.ongoing(fsm.WRITE_CSR), + If(fsm.ongoing("WRITE_CSR"), self.csr.we.eq(1) ).Else( self.csr.we.eq(0) diff --git a/miscope/bridges/spi2csr/tools/__init__.py b/miscope/com/uart2csr/host/__init__.py similarity index 100% rename from miscope/bridges/spi2csr/tools/__init__.py rename to miscope/com/uart2csr/host/__init__.py diff --git a/miscope/bridges/uart2csr/tools/uart2Csr.py b/miscope/com/uart2csr/host/uart2csr.py similarity index 89% rename from miscope/bridges/uart2csr/tools/uart2Csr.py rename to miscope/com/uart2csr/host/uart2csr.py index 1e58d946..c1ce7d08 100644 --- a/miscope/bridges/uart2csr/tools/uart2Csr.py +++ b/miscope/com/uart2csr/host/uart2csr.py @@ -18,10 +18,18 @@ class Uart2Csr: self.baudrate = baudrate self.debug = debug self.uart = serial.Serial(port, baudrate, timeout=0.25) - - def read(self, addr, burst_length=1): + + 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) @@ -50,13 +58,14 @@ class Uart2Csr: print("RD @ %04X" %addr) return r - def write(self, addr, data): + 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, diff --git a/miscope/bridges/uart2csr/uart.py b/miscope/com/uart2csr/uart.py similarity index 100% rename from miscope/bridges/uart2csr/uart.py rename to miscope/com/uart2csr/uart.py 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/bridges/uart2csr/tools/__init__.py b/miscope/std/__init__.py similarity index 100% rename from miscope/bridges/uart2csr/tools/__init__.py rename to miscope/std/__init__.py 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/tools/conv.py b/miscope/std/conv.py similarity index 100% rename from miscope/tools/conv.py rename to miscope/std/conv.py diff --git a/examples/de0_nano/misc.py b/miscope/std/misc.py similarity index 86% rename from examples/de0_nano/misc.py rename to miscope/std/misc.py index 1067a5c4..359f8f56 100644 --- a/examples/de0_nano/misc.py +++ b/miscope/std/misc.py @@ -1,15 +1,19 @@ -from migen.fhdl.structure import * -from migen.fhdl.module import Module +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, domain="sys"): + def __init__(self, i=None, o=None): 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}) + 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"): @@ -17,9 +21,8 @@ class FallingEdge(Module): 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}) + 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): diff --git a/miscope/tools/truthtable.py b/miscope/std/truthtable.py similarity index 100% rename from miscope/tools/truthtable.py rename to miscope/std/truthtable.py diff --git a/miscope/tools/vcd.py b/miscope/std/vcd.py similarity index 100% rename from miscope/tools/vcd.py rename to miscope/std/vcd.py diff --git a/miscope/tools/__init__.py b/miscope/tools/__init__.py deleted file mode 100644 index e69de29b..00000000 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/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() -- 2.30.2