├── unittests ├── __init__.py ├── rc │ ├── prj.yaml │ ├── source.yaml │ ├── tb.sv │ ├── simctrl.yaml │ ├── gen.py │ └── sim_ctrl.sv ├── tf │ ├── prj.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── view.gtkw │ └── gen.py ├── inertial │ ├── prj.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── view.gtkw │ └── gen.py ├── rlc │ ├── prj.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── view.gtkw │ └── gen.py ├── multi_clock │ ├── prj.yaml │ ├── source.yaml │ ├── tb.sv │ ├── simctrl.yaml │ ├── clks.yaml │ ├── sim_ctrl.sv │ ├── gen.py │ └── osc_checker.sv ├── multicase │ ├── prj.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── view.gtkw │ └── gen.py ├── buck │ ├── config.json │ ├── prj.yaml │ ├── simctrl.yaml │ ├── view_fpga.gtkw │ ├── view.gtkw │ ├── tb.sv │ ├── interactive_sim.py │ └── gen.py ├── filter │ ├── source.yaml │ ├── my_custom_simctrl.yaml │ ├── prj.yaml │ ├── sim_ctrl.sv │ ├── tb.sv │ ├── view.gtkw │ ├── view_fpga.gtkw │ ├── my_filter.py │ ├── interactive_sim.py │ └── view.svcf ├── function │ ├── prj.yaml │ ├── simctrl.yaml │ ├── source.yaml │ ├── tb.sv │ ├── gen.py │ └── sim_ctrl.sv ├── one_clock │ ├── prj.yaml │ ├── clks.yaml │ ├── simctrl.yaml │ ├── source.yaml │ ├── tb.sv │ ├── gen.py │ └── sim_ctrl.sv ├── error_recognition │ ├── prj.yaml │ └── tb.sv ├── firmware │ ├── prj.yaml │ ├── source.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── sim_ctrl.sv │ └── main.c ├── custom_firmware │ ├── prj.yaml │ ├── source.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── sim_ctrl.sv │ └── main.c ├── bitwise │ ├── gen.py │ └── tb.sv ├── enums.py ├── conftest.py └── waveform.py ├── anasymod ├── emu │ ├── __init__.py │ └── xsct_emu.py ├── sim │ ├── __init__.py │ ├── sim.py │ ├── xcelium.make_target │ ├── vivado.py │ └── icarus.py ├── utils │ ├── __init__.py │ └── statpro.py ├── viewer │ ├── __init__.py │ ├── scansion.py │ ├── viewer.py │ ├── simvision.py │ └── gtkwave.py ├── fpga_boards │ └── __init__.py ├── generators │ ├── __init__.py │ ├── xsct.py │ └── codegen.py ├── sim_ctrl │ ├── __init__.py │ ├── ctrlinfra.py │ ├── console_print.py │ ├── vio_ctrlinfra.py │ └── uart_zynq_ctrlinfra.py ├── structures │ ├── __init__.py │ ├── module_base.py │ ├── signal_base.py │ ├── port_base.py │ ├── firmware_gpio.py │ ├── module_traceport.py │ ├── module_clk_manager.py │ ├── uart_zynq_firmware_appcode.py │ └── module_emu_clks.py ├── templates │ ├── __init__.py │ ├── templ.py │ ├── dbg_hub.py │ ├── ext_clk.py │ ├── generic_ip.py │ ├── ila.py │ ├── clk_wiz.py │ ├── vio_wiz.py │ ├── xsct_build.py │ ├── probe_extract.py │ └── launch_ILA_tcl.py ├── __init__.py ├── defines.py ├── verilog │ ├── clkgate.sv │ ├── calc_emu_time.sv │ ├── time_manager.sv │ ├── anasymod.sv │ ├── gen_emu_clks.sv │ ├── osc_model_anasymod.sv │ ├── regmap.sv │ └── ctrl_anasymod.sv ├── files.py ├── probe_config.py ├── base_config.py ├── enums.py └── plugins.py ├── examples ├── afe │ ├── .gitignore │ ├── clks.yaml │ ├── prj.yaml │ ├── source.yaml │ └── sim_ctrl.sv ├── circuit │ ├── prj.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── view.gtkw │ ├── view_fpga.gtkw │ ├── gen.py │ └── view.svcf ├── rectifier │ ├── prj.yaml │ ├── simctrl.yaml │ ├── view.gtkw │ ├── tb.sv │ └── gen.py ├── buck_circuit │ ├── prj.yaml │ ├── simctrl.yaml │ ├── view.gtkw │ ├── view_fpga.gtkw │ ├── tb.sv │ └── gen.py ├── comparator │ ├── prj.yaml │ ├── simctrl.yaml │ ├── gen.py │ ├── view.gtkw │ └── tb.sv ├── inductor_issue │ ├── prj.yaml │ ├── simctrl.yaml │ ├── view.gtkw │ ├── tb.sv │ └── gen.py ├── current_switch │ ├── prj.yaml │ ├── simctrl.yaml │ ├── tb.sv │ ├── gen.py │ └── view.gtkw └── current_switch_array │ ├── prj.yaml │ ├── simctrl.yaml │ ├── view.gtkw │ ├── gen.py │ └── tb.sv ├── MANIFEST.in ├── .gitignore ├── codecov.yml ├── .github └── workflows │ ├── release.yml │ └── regression.yml ├── LICENSE ├── regress.sh ├── .buildkite └── pipeline.yml └── setup.py /unittests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/emu/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/sim/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/viewer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/fpga_boards/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/generators/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/sim_ctrl/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/structures/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /anasymod/templates/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/afe/.gitignore: -------------------------------------------------------------------------------- 1 | simctrl.yaml -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include anasymod/verilog/*.*v 2 | include anasymod/verilog/*.bd -------------------------------------------------------------------------------- /unittests/rc/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | board_name: PYNQ_Z1 4 | plugins: ['msdsl'] 5 | emu_clk_freq: 10e6 6 | -------------------------------------------------------------------------------- /unittests/tf/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 -------------------------------------------------------------------------------- /unittests/tf/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 5 5 | -------------------------------------------------------------------------------- /examples/circuit/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 -------------------------------------------------------------------------------- /examples/circuit/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 1.5 -------------------------------------------------------------------------------- /examples/rectifier/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 10e-9 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 -------------------------------------------------------------------------------- /unittests/inertial/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 50e-9 3 | CPU_TARGET: 4 | sim: 5 | tstop: 310e-6 -------------------------------------------------------------------------------- /unittests/rlc/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.01e-6 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 -------------------------------------------------------------------------------- /examples/buck_circuit/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 50e-9 3 | CPU_TARGET: 4 | sim: 5 | tstop: 100e-6 -------------------------------------------------------------------------------- /examples/comparator/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 -------------------------------------------------------------------------------- /examples/inductor_issue/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 1e-10 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 -------------------------------------------------------------------------------- /unittests/multi_clock/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | board_name: PYNQ_Z1 4 | plugins: ['msdsl'] 5 | emu_clk_freq: 10e6 6 | -------------------------------------------------------------------------------- /unittests/multicase/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 -------------------------------------------------------------------------------- /examples/current_switch/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.03333333333e-9 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-9 -------------------------------------------------------------------------------- /examples/current_switch_array/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.03333333333e-9 3 | CPU_TARGET: 4 | sim: 5 | tstop: 5e-9 -------------------------------------------------------------------------------- /unittests/buck/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ind": 2.2e-6, 3 | "c_load": 10e-6, 4 | "r_load": 5.5, 5 | "r_snub": 300, 6 | "c_snub": 100e-12, 7 | "r_sw": 1.0 8 | } -------------------------------------------------------------------------------- /unittests/filter/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | sim_ctrl: 3 | files: './sim_ctrl.*v' 4 | functional_models: 5 | filter: 6 | files: './my_filter.py' -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .simvision 2 | .cache 3 | .Xil 4 | .idea 5 | .DS_Store 6 | *.jou 7 | *.log 8 | *.str 9 | *.egg-info 10 | *.s4p 11 | __pycache__ 12 | build 13 | dist/ 14 | -------------------------------------------------------------------------------- /unittests/function/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | board_name: PYNQ_Z1 4 | plugins: ['msdsl'] 5 | emu_clk_freq: 10e6 6 | cpu_debug_mode: true 7 | cpu_debug_hierarchies: [[0, 'top']] -------------------------------------------------------------------------------- /unittests/one_clock/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | board_name: PYNQ_Z1 4 | plugins: ['msdsl'] 5 | emu_clk_freq: 10e6 6 | 7 | FPGA_TARGET: 8 | fpga: 9 | tstop: 10e-6 10 | -------------------------------------------------------------------------------- /unittests/inertial/simctrl.yaml: -------------------------------------------------------------------------------- 1 | digital_probes: 2 | in__probe: 3 | abspath: 'tb_i.in_' 4 | width: 1 5 | out_probe: 6 | abspath: 'tb_i.out' 7 | width: 1 -------------------------------------------------------------------------------- /unittests/function/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_ctrl_inputs: 2 | in_: 3 | abspath: 'tb_i.in_' 4 | range: 10 5 | init_value: 0.0 6 | analog_ctrl_outputs: 7 | out: 8 | abspath: 'tb_i.out' 9 | range: 10 -------------------------------------------------------------------------------- /anasymod/__init__.py: -------------------------------------------------------------------------------- 1 | from .files import get_full_path 2 | from .util import json2obj, ExampleControl 3 | from anasymod.utils import statpro as __statpro 4 | __statpro.statpro_update(__statpro.FEATURES.anasymod_import) -------------------------------------------------------------------------------- /unittests/rlc/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 15 5 | v_in_probe: 6 | abspath: 'tb_i.v_in' 7 | range: 1.01 8 | -------------------------------------------------------------------------------- /unittests/error_recognition/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | CPU_TARGET: 4 | sim: 5 | tstop: 10e-6 6 | FPGA_TARGET: 7 | fpga: 8 | tstop: 10e-6 9 | -------------------------------------------------------------------------------- /examples/rectifier/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 1.5 5 | digital_probes: 6 | gate_probe: 7 | abspath: 'tb_i.gate' 8 | width: 1 -------------------------------------------------------------------------------- /unittests/multicase/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 1.5 5 | digital_probes: 6 | ctrl_probe: 7 | abspath: 'tb_i.ctrl' 8 | width: 1 -------------------------------------------------------------------------------- /unittests/filter/my_custom_simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 1.5 5 | digital_probes: 6 | osc_cke: 7 | abspath: 'def_osc_i.cke' 8 | width: 1 -------------------------------------------------------------------------------- /unittests/firmware/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | board_name: PYNQ_Z1 4 | plugins: ['msdsl'] 5 | emu_clk_freq: 10e6 6 | FPGA_TARGET: 7 | fpga: 8 | fpga_sim_ctrl: 'UART_ZYNQ' 9 | #custom_zynq_firmware: True -------------------------------------------------------------------------------- /unittests/custom_firmware/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | board_name: PYNQ_Z1 4 | plugins: ['msdsl'] 5 | emu_clk_freq: 10e6 6 | FPGA_TARGET: 7 | fpga: 8 | fpga_sim_ctrl: 'UART_ZYNQ' 9 | custom_zynq_firmware: True -------------------------------------------------------------------------------- /examples/afe/clks.yaml: -------------------------------------------------------------------------------- 1 | derived_clks: 2 | tb_emu_io: 3 | abspath: 'tb_i' 4 | emu_clk: 'emu_clk' 5 | emu_rst: 'emu_rst' 6 | emu_dt: 'emu_dt' 7 | dt_req: 'dt_req' 8 | # ext_dt: 9 | # abspath: 'tb_i' 10 | # dt_req: 'ext_dt' -------------------------------------------------------------------------------- /unittests/one_clock/clks.yaml: -------------------------------------------------------------------------------- 1 | derived_clks: 2 | tb_i: 3 | abspath: 'tb_i' 4 | emu_clk: 'emu_clk' 5 | emu_rst: 'emu_rst' 6 | emu_dt: 'emu_dt' 7 | dt_req: 'dt_req' 8 | gated_clk_req: 'clk_val' 9 | gated_clk: 'clk_i' 10 | -------------------------------------------------------------------------------- /unittests/one_clock/simctrl.yaml: -------------------------------------------------------------------------------- 1 | digital_ctrl_inputs: 2 | t_lo: 3 | abspath: 'tb_i.t_lo' 4 | width: 32 5 | t_hi: 6 | abspath: 'tb_i.t_hi' 7 | width: 32 8 | 9 | digital_ctrl_outputs: 10 | clk_i: 11 | abspath: 'tb_i.clk_i' -------------------------------------------------------------------------------- /examples/afe/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | board_name: ZC706 4 | plugins: ['msdsl'] 5 | emu_clk_freq: 10e6 6 | flatten_hierarchy': 'none' 7 | vivado_stack: 2000 8 | ila_depth: 4096 9 | # cpu_debug_mode: 1 10 | # cpu_debug_hierarchies: [[0, "top"]] 11 | -------------------------------------------------------------------------------- /unittests/buck/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 50e-9 3 | ila_depth: 16384 4 | # board_name: PYNQ_Z1 5 | CPU_TARGET: 6 | sim: 7 | tstop: 100e-6 8 | FPGA_TARGET: 9 | fpga: 10 | fpga_sim_ctrl: 'VIVADO_VIO' -------------------------------------------------------------------------------- /unittests/rc/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | sim_ctrl: 3 | files: "sim_ctrl.sv" 4 | fileset: "sim" 5 | defines: 6 | DT_MSDSL: 7 | name: DT_MSDSL 8 | value: 0.1e-6 9 | SIMULATION_MODE_MSDSL: 10 | name: SIMULATION_MODE_MSDSL 11 | fileset: "sim" 12 | -------------------------------------------------------------------------------- /unittests/error_recognition/tb.sv: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1ns/1ps 3 | 4 | `include "svreal.sv" 5 | `include "msdsl.sv" 6 | 7 | `default_nettype none 8 | 9 | module tb; 10 | initial begin 11 | $error("test error"); 12 | end 13 | endmodule 14 | 15 | `default_nettype wire -------------------------------------------------------------------------------- /unittests/function/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | sim_ctrl: 3 | files: "sim_ctrl.sv" 4 | fileset: "sim" 5 | defines: 6 | DT_MSDSL: 7 | name: DT_MSDSL 8 | value: 0.1e-6 9 | SIMULATION_MODE_MSDSL: 10 | name: SIMULATION_MODE_MSDSL 11 | fileset: "sim" 12 | -------------------------------------------------------------------------------- /unittests/one_clock/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | sim_ctrl: 3 | files: "sim_ctrl.sv" 4 | fileset: "sim" 5 | defines: 6 | DT_MSDSL: 7 | name: DT_MSDSL 8 | value: 0.1e-6 9 | SIMULATION_MODE_MSDSL: 10 | name: SIMULATION_MODE_MSDSL 11 | fileset: "sim" 12 | -------------------------------------------------------------------------------- /unittests/firmware/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | sim_ctrl: 3 | files: "sim_ctrl.sv" 4 | fileset: "sim" 5 | defines: 6 | DT_MSDSL: 7 | name: DT_MSDSL 8 | value: 0.1e-6 9 | SIMULATION_MODE_MSDSL: 10 | name: SIMULATION_MODE_MSDSL 11 | fileset: "sim" 12 | -------------------------------------------------------------------------------- /examples/comparator/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | in_p_probe: 3 | abspath: 'tb_i.in_p' 4 | range: 10 5 | in_n_probe: 6 | abspath: 'tb_i.in_n' 7 | range: 3.45 8 | digital_probes: 9 | out_probe: 10 | abspath: 'tb_i.out' 11 | width: 1 -------------------------------------------------------------------------------- /examples/current_switch/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 5 5 | v_in_probe: 6 | abspath: 'tb_i.v_in' 7 | range: 1.3 8 | digital_probes: 9 | ctrl_probe: 10 | abspath: 'tb_i.gate' 11 | width: 1 -------------------------------------------------------------------------------- /examples/inductor_issue/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 1.5 5 | v_in_probe: 6 | abspath: 'tb_i.v_in' 7 | range: 1.5 8 | digital_probes: 9 | gate_probe: 10 | abspath: 'tb_i.gate' 11 | width: 1 -------------------------------------------------------------------------------- /examples/current_switch_array/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 5 5 | v_in_probe: 6 | abspath: 'tb_i.v_in' 7 | range: 1.3 8 | digital_probes: 9 | ctrl_probe: 10 | abspath: 'tb_i.ctrl' 11 | width: 47 -------------------------------------------------------------------------------- /unittests/function/tb.sv: -------------------------------------------------------------------------------- 1 | `include "svreal.sv" 2 | 3 | module tb; 4 | // signals 5 | `MAKE_REAL(in_, 10.0); 6 | `MAKE_REAL(out, 10.0); 7 | 8 | // function 9 | model #( 10 | `PASS_REAL(in_, in_), 11 | `PASS_REAL(out, out) 12 | ) model_i ( 13 | .in_(in_), 14 | .out(out) 15 | ); 16 | endmodule 17 | -------------------------------------------------------------------------------- /unittests/multi_clock/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | osc_checker: 3 | files: "osc_checker.sv" 4 | fileset: "sim" 5 | sim_ctrl: 6 | files: "sim_ctrl.sv" 7 | fileset: "sim" 8 | defines: 9 | DT_MSDSL: 10 | name: DT_MSDSL 11 | value: 0.1e-6 12 | SIMULATION_MODE_MSDSL: 13 | name: SIMULATION_MODE_MSDSL 14 | fileset: "sim" 15 | -------------------------------------------------------------------------------- /unittests/custom_firmware/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | sim_ctrl: 3 | files: "sim_ctrl.sv" 4 | fileset: "sim" 5 | firmware_files: 6 | main_fw: 7 | files: "main.c" 8 | defines: 9 | DT_MSDSL: 10 | name: DT_MSDSL 11 | value: 0.1e-6 12 | SIMULATION_MODE_MSDSL: 13 | name: SIMULATION_MODE_MSDSL 14 | fileset: "sim" 15 | -------------------------------------------------------------------------------- /unittests/rc/tb.sv: -------------------------------------------------------------------------------- 1 | `include "svreal.sv" 2 | 3 | module tb; 4 | // analog signals 5 | `MAKE_REAL(v_in, 10.0); 6 | `MAKE_REAL(v_out, 10.0); 7 | 8 | // filter 9 | model #( 10 | `PASS_REAL(v_in, v_in), 11 | `PASS_REAL(v_out, v_out) 12 | ) model_i ( 13 | .v_in(v_in), 14 | .v_out(v_out) 15 | ); 16 | endmodule 17 | -------------------------------------------------------------------------------- /unittests/multi_clock/tb.sv: -------------------------------------------------------------------------------- 1 | module tb; 2 | // emulator I/O 3 | (* dont_touch = "true" *) logic clk_val_0; 4 | (* dont_touch = "true" *) logic clk_val_1; 5 | (* dont_touch = "true" *) logic clk_0; 6 | (* dont_touch = "true" *) logic clk_1; 7 | 8 | // oscillators 9 | osc osc_0 (.clk_val(clk_val_0)); 10 | osc osc_1 (.clk_val(clk_val_1)); 11 | endmodule 12 | -------------------------------------------------------------------------------- /anasymod/viewer/scansion.py: -------------------------------------------------------------------------------- 1 | from anasymod.viewer.viewer import Viewer 2 | from anasymod.util import call 3 | 4 | class ScansionViewer(Viewer): 5 | def view(self): 6 | # build command 7 | #cmd = ['open', '/Applications/Scansion.app', self.target.cfg['vcd_path']] 8 | cmd = ['open', '/Applications/Scansion.app'] 9 | 10 | # run command 11 | call(cmd) -------------------------------------------------------------------------------- /anasymod/viewer/viewer.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from anasymod.config import EmuConfig 4 | from anasymod.targets import Target 5 | 6 | class Viewer(ABC): 7 | def __init__(self, target: Target): 8 | self.cfg = target.prj_cfg 9 | self.target = target 10 | 11 | @abstractmethod 12 | def view(self, result_file=None): 13 | pass -------------------------------------------------------------------------------- /unittests/firmware/simctrl.yaml: -------------------------------------------------------------------------------- 1 | digital_ctrl_inputs: 2 | a_in: 3 | abspath: 'tb_i.a_in' 4 | width: 8 5 | init_value: 0 6 | b_in: 7 | abspath: 'tb_i.b_in' 8 | width: 8 9 | init_value: 0 10 | mode_in: 11 | abspath: 'tb_i.mode_in' 12 | width: 8 13 | init_value: 0 14 | digital_ctrl_outputs: 15 | c_out: 16 | abspath: 'tb_i.c_out' 17 | width: 8 -------------------------------------------------------------------------------- /unittests/rc/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_in_probe: 3 | abspath: 'tb_i.v_in' 4 | range: 10.0 5 | v_out_probe: 6 | abspath: 'tb_i.v_out' 7 | range: 10.0 8 | analog_ctrl_inputs: 9 | v_in: 10 | abspath: 'tb_i.v_in' 11 | range: 10 12 | init_value: 0.0 13 | analog_ctrl_outputs: 14 | v_out: 15 | abspath: 'tb_i.v_out' 16 | range: 10 -------------------------------------------------------------------------------- /unittests/custom_firmware/simctrl.yaml: -------------------------------------------------------------------------------- 1 | digital_ctrl_inputs: 2 | a_in: 3 | abspath: 'tb_i.a_in' 4 | width: 8 5 | init_value: 0 6 | b_in: 7 | abspath: 'tb_i.b_in' 8 | width: 8 9 | init_value: 0 10 | mode_in: 11 | abspath: 'tb_i.mode_in' 12 | width: 8 13 | init_value: 0 14 | digital_ctrl_outputs: 15 | c_out: 16 | abspath: 'tb_i.c_out' 17 | width: 8 -------------------------------------------------------------------------------- /unittests/filter/prj.yaml: -------------------------------------------------------------------------------- 1 | PROJECT: 2 | dt: 0.1e-6 3 | cpu_debug_mode: 1 4 | cpu_debug_hierarchies: [[0, 'top.tb_i.filter_i']] 5 | CPU_TARGET: 6 | sim: 7 | tstop: 10e-6 8 | simctrl_path: './my_custom_simctrl.yaml' 9 | FPGA_TARGET: 10 | fpga: 11 | fpga_sim_ctrl: 'VIVADO_VIO' 12 | tstop: 10e-6 13 | simctrl_path: './my_custom_simctrl.yaml' 14 | -------------------------------------------------------------------------------- /unittests/multi_clock/simctrl.yaml: -------------------------------------------------------------------------------- 1 | digital_ctrl_inputs: 2 | t_lo_0: 3 | abspath: 'tb_i.osc_0.t_lo' 4 | width: 32 5 | t_hi_0: 6 | abspath: 'tb_i.osc_0.t_hi' 7 | width: 32 8 | t_lo_1: 9 | abspath: 'tb_i.osc_1.t_lo' 10 | width: 32 11 | t_hi_1: 12 | abspath: 'tb_i.osc_1.t_hi' 13 | width: 32 14 | 15 | digital_ctrl_outputs: 16 | clk_0: 17 | abspath: 'tb_i.clk_0' 18 | clk_1: 19 | abspath: 'tb_i.clk_1' -------------------------------------------------------------------------------- /anasymod/defines.py: -------------------------------------------------------------------------------- 1 | class Define(): 2 | def __init__(self, name, value=None, fileset=r"default"): 3 | self.name = name 4 | """ type(str) : mandatory setting; name of define. """ 5 | 6 | self.value = value 7 | """ type(str) : value of define. """ 8 | 9 | self.define = {self.name: self.value} 10 | 11 | self.fileset = fileset 12 | """ type(str) : Fileset, the source shall be associsted with. """ -------------------------------------------------------------------------------- /unittests/inertial/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // gate drive signal 13 | `PWM(0.50, 10e3, in_); 14 | 15 | // filter instantiation 16 | logic out; 17 | inertial interial_i ( 18 | .in_(in_), 19 | .out(out) 20 | ); 21 | 22 | endmodule 23 | 24 | `default_nettype wire -------------------------------------------------------------------------------- /examples/afe/source.yaml: -------------------------------------------------------------------------------- 1 | verilog_sources: 2 | sim_ctrl: 3 | files: "sim_ctrl.sv" 4 | fileset: "sim" 5 | ams_models: 6 | files: 7 | - "build/channel/channel.sv" 8 | - "build/ctle1/ctle1.sv" 9 | - "build/ctle2/ctle2.sv" 10 | - "build/ctle3/ctle3.sv" 11 | - "build/nonlin/nonlin.sv" 12 | - "build/unfm/unfm.sv" 13 | - "build/osc/osc.sv" 14 | defines: 15 | DT_MSDSL: 16 | name: DT_MSDSL 17 | value: 62.5e-12 -------------------------------------------------------------------------------- /unittests/filter/sim_ctrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | `include "svreal.sv" 4 | //`include "math.sv" 5 | `include "msdsl.sv" 6 | 7 | `default_nettype none 8 | 9 | module sim_ctrl ( 10 | //input `DATA_TYPE_REAL(`LONG_WIDTH_REAL) primpf 11 | ); 12 | 13 | //`PROBE_ANALOG_CTRL(primpf, top.tb_i.v_out); 14 | 15 | //`PROBE_DIGITAL(primpf, `LONG_WIDTH_REAL); 16 | 17 | //`PRINT_FORMAT_REAL(top.tb_i.v_out); 18 | 19 | 20 | endmodule 21 | 22 | `default_nettype wire -------------------------------------------------------------------------------- /unittests/buck/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 10 5 | i_ind_probe: 6 | abspath: 'tb_i.i_ind' 7 | range: 20 8 | digital_probes: 9 | ls_probe: 10 | abspath: 'tb_i.ls' 11 | width: 1 12 | hs_probe: 13 | abspath: 'tb_i.hs' 14 | width: 1 15 | ls_en_probe: 16 | abspath: 'tb_i.ls_en' 17 | width: 1 -------------------------------------------------------------------------------- /anasymod/verilog/clkgate.sv: -------------------------------------------------------------------------------- 1 | // Gated clock model 2 | // *** ONLY FOR SIMULATION *** 3 | 4 | `timescale 1ns/1ps 5 | 6 | `default_nettype none 7 | 8 | module ana_clkgate( 9 | input wire en, 10 | input wire clk, 11 | output wire gated 12 | ); 13 | 14 | reg en_latched = 0; 15 | 16 | always @* begin 17 | if (clk == 1'b0) begin 18 | en_latched <= en; 19 | end 20 | end 21 | 22 | assign gated = clk & en_latched; 23 | 24 | endmodule 25 | 26 | `default_nettype wire -------------------------------------------------------------------------------- /examples/buck_circuit/simctrl.yaml: -------------------------------------------------------------------------------- 1 | analog_probes: 2 | v_out_probe: 3 | abspath: 'tb_i.v_out' 4 | range: 10 5 | i_ind_probe: 6 | abspath: 'tb_i.i_ind' 7 | range: 20 8 | digital_probes: 9 | ls_probe: 10 | abspath: 'tb_i.ls' 11 | width: 1 12 | hs_probe: 13 | abspath: 'tb_i.hs' 14 | width: 1 15 | ls_en_probe: 16 | abspath: 'tb_i.ls_en' 17 | width: 1 -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | # configuration related to pull request comments 2 | comment: no # do not comment PR with the result 3 | 4 | coverage: 5 | range: 50..90 # coverage lower than 50 is red, higher than 90 green, between color code 6 | 7 | status: 8 | project: # settings affecting project coverage 9 | default: 10 | target: auto # auto % coverage target 11 | threshold: 5% # allow for 5% reduction of coverage without failing 12 | 13 | # do not run coverage on patch nor changes 14 | patch: false 15 | -------------------------------------------------------------------------------- /anasymod/templates/templ.py: -------------------------------------------------------------------------------- 1 | from jinja2 import Environment 2 | 3 | class JinjaTempl: 4 | def __init__(self, trim_blocks=False, lstrip_blocks=False): 5 | self.trim_blocks = trim_blocks 6 | self.lstrip_blocks = lstrip_blocks 7 | 8 | def render(self): 9 | t = Environment(trim_blocks=self.trim_blocks, lstrip_blocks=self.lstrip_blocks).from_string(self.TEMPLATE_TEXT) 10 | #t = Template(self.TEMPLATE_TEXT) 11 | 12 | return t.render(subst=self)+'\n' 13 | 14 | TEMPLATE_TEXT = '' -------------------------------------------------------------------------------- /unittests/multi_clock/clks.yaml: -------------------------------------------------------------------------------- 1 | derived_clks: 2 | clk_0: 3 | abspath: 'tb_i' 4 | gated_clk_req: 'clk_val_0' 5 | gated_clk: 'clk_0' 6 | clk_1: 7 | abspath: 'tb_i' 8 | gated_clk_req: 'clk_val_1' 9 | gated_clk: 'clk_1' 10 | osc_0: 11 | abspath: 'tb_i.osc_0' 12 | emu_clk: 'emu_clk' 13 | emu_rst: 'emu_rst' 14 | emu_dt: 'emu_dt' 15 | dt_req: 'dt_req' 16 | osc_1: 17 | abspath: 'tb_i.osc_1' 18 | emu_clk: 'emu_clk' 19 | emu_rst: 'emu_rst' 20 | emu_dt: 'emu_dt' 21 | dt_req: 'dt_req' -------------------------------------------------------------------------------- /anasymod/sim/sim.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from anasymod.targets import CPUTarget 3 | from anasymod.config import EmuConfig 4 | 5 | class Simulator(ABC): 6 | def __init__(self, target: CPUTarget, flags=None): 7 | # set defaults 8 | if flags is None: 9 | flags = [] 10 | 11 | # save settings 12 | self.cfg = target.prj_cfg 13 | self.target = target 14 | self.flags = flags 15 | 16 | @abstractmethod 17 | def simulate(self): 18 | pass 19 | -------------------------------------------------------------------------------- /examples/afe/sim_ctrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1s/1ns 2 | `include "svreal.sv" 3 | 4 | module sim_ctrl #( 5 | `DECL_REAL(tlo), 6 | `DECL_REAL(thi) 7 | ) ( 8 | `OUTPUT_REAL(tlo), 9 | `OUTPUT_REAL(thi) 10 | ); 11 | `include "anasymod.sv" 12 | 13 | `ASSIGN_CONST_REAL(62.5e-12, tlo); 14 | `ASSIGN_CONST_REAL(62.5e-12, thi); 15 | 16 | initial begin 17 | // clamp the maximum emulator timestep 18 | set_max_emu_dt(31.25e-12); 19 | 20 | // wait a certain amount of time 21 | #(10us); 22 | 23 | // end simulation 24 | $finish; 25 | end 26 | endmodule 27 | -------------------------------------------------------------------------------- /unittests/tf/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // input is a fixed value 13 | `MAKE_CONST_REAL(1.0, v_in); 14 | 15 | // output has range range +/- 5.0 16 | `MAKE_REAL(v_out, 5.0); 17 | 18 | // filter instantiation 19 | filter #( 20 | `PASS_REAL(v_in, v_in), 21 | `PASS_REAL(v_out, v_out) 22 | ) filter_i ( 23 | .v_in(v_in), 24 | .v_out(v_out) 25 | ); 26 | 27 | endmodule 28 | 29 | `default_nettype wire -------------------------------------------------------------------------------- /examples/circuit/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // input is a fixed value 13 | `MAKE_CONST_REAL(1.0, v_in); 14 | 15 | // output has range range +/- 1.5 16 | `MAKE_REAL(v_out, 1.5); 17 | 18 | // filter instantiation 19 | filter #( 20 | `PASS_REAL(v_in, v_in), 21 | `PASS_REAL(v_out, v_out) 22 | ) filter_i ( 23 | .v_in(v_in), 24 | .v_out(v_out) 25 | ); 26 | 27 | endmodule 28 | 29 | `default_nettype wire -------------------------------------------------------------------------------- /unittests/filter/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // input is a fixed value 13 | `MAKE_CONST_REAL(1.0, v_in); 14 | 15 | // output has range range +/- 1.5 16 | `MAKE_REAL(v_out, 1.5); 17 | 18 | // filter instantiation 19 | filter #( 20 | `PASS_REAL(v_in, v_in), 21 | `PASS_REAL(v_out, v_out) 22 | ) filter_i ( 23 | .v_in(v_in), 24 | .v_out(v_out) 25 | ); 26 | 27 | endmodule 28 | 29 | `default_nettype wire -------------------------------------------------------------------------------- /anasymod/structures/module_base.py: -------------------------------------------------------------------------------- 1 | class ModuleBase(): 2 | """ 3 | This is the base class for module structure generation. 4 | """ 5 | def gen_module(self): 6 | """ 7 | Generates sv code for module body. 8 | :return: Generated code of module body. 9 | """ 10 | pass 11 | 12 | def gen_instantiation(self): 13 | """ 14 | Generates sv code for module instantiation. 15 | :return: Generated code of module instantiation. 16 | """ 17 | pass 18 | 19 | #note: it shall be possible to cluster ports -> all analog clks, all dig clks, all ctrl signals -------------------------------------------------------------------------------- /examples/comparator/gen.py: -------------------------------------------------------------------------------- 1 | from msdsl import MixedSignalModel 2 | from anasymod import ExampleControl 3 | 4 | def main(): 5 | ctrl = ExampleControl() 6 | 7 | # define ports 8 | m = MixedSignalModel('comparator', dt=ctrl.dt) 9 | m.add_analog_input('in_p') 10 | m.add_analog_input('in_n') 11 | m.add_digital_output('out', init=0) 12 | m.add_digital_input('clk') 13 | 14 | # define behavior 15 | m.immediate_assign('out_async', m.in_p > m.in_n) 16 | m.next_cycle_assign(m.out, m.out_async, clk=m.clk, rst="1'b0") 17 | 18 | # write model 19 | ctrl.write_model(m) 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /unittests/multicase/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // I/O definition 13 | `MAKE_CONST_REAL(1.0, v_in); 14 | `MAKE_REAL(v_out, 1.5); 15 | 16 | // gate drive signal 17 | `PWM(0.50, 300e3, ctrl); 18 | 19 | // filter instantiation 20 | filter #( 21 | `PASS_REAL(v_in, v_in), 22 | `PASS_REAL(v_out, v_out) 23 | ) filter_i ( 24 | .v_in(v_in), 25 | .v_out(v_out), 26 | .ctrl(ctrl) 27 | ); 28 | 29 | endmodule 30 | 31 | `default_nettype wire -------------------------------------------------------------------------------- /examples/current_switch/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // analog inputs 13 | `MAKE_CONST_REAL(1.3, v_in); 14 | 15 | // analog outputs 16 | `MAKE_REAL(v_out, 5.0); 17 | 18 | // digital inputs 19 | `PWM(0.50, 3e9, ctrl); 20 | 21 | // comparator instantiation 22 | current_switch #( 23 | `PASS_REAL(v_in, v_in), 24 | `PASS_REAL(v_out, v_out) 25 | ) current_switch_i ( 26 | .v_in(v_in), 27 | .ctrl(ctrl), 28 | .v_out(v_out) 29 | ); 30 | 31 | endmodule 32 | 33 | `default_nettype wire -------------------------------------------------------------------------------- /examples/circuit/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Tue Apr 9 22:33:48 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/filter/build/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Tue Apr 9 22:33:43 2019" 7 | [dumpfile_size] 6088 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/filter/view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-21.649426 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 223 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @10029 18 | top.v_out_probe 19 | @20000 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | [pattern_trace] 1 27 | [pattern_trace] 0 28 | -------------------------------------------------------------------------------- /unittests/filter/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Tue Apr 9 22:33:48 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/filter/build/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Tue Apr 9 22:33:43 2019" 7 | [dumpfile_size] 6088 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/filter/view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-21.649426 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 223 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @10029 18 | top.v_out_probe 19 | @20000 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | [pattern_trace] 1 27 | [pattern_trace] 0 28 | -------------------------------------------------------------------------------- /unittests/tf/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.65 (w)1999-2015 BSI 3 | [*] Tue Jan 29 11:11:54 2019 4 | [*] 5 | [dumpfile] "C:\Users\herbstst\Emulation\anasymod\tests\build\dump.vcd" 6 | [dumpfile_mtime] "Tue Jan 29 11:10:35 2019" 7 | [dumpfile_size] 3468 8 | [savefile] "C:\Users\herbstst\Emulation\anasymod\tests\filter\view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-21.591291 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 197 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @8420 18 | top.v_out_probe 19 | @20001 20 | - 21 | @20000 22 | - 23 | - 24 | - 25 | - 26 | - 27 | [pattern_trace] 1 28 | [pattern_trace] 0 29 | -------------------------------------------------------------------------------- /examples/circuit/view_fpga.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Wed Apr 10 03:59:47 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/filter/build/vcd/top_fpga.vcd" 6 | [dumpfile_mtime] "Wed Apr 10 03:58:57 2019" 7 | [dumpfile_size] 244625 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/filter/view_fpga.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-11.683785 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 223 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @10028 18 | tb_i.v_out_probe 19 | @20000 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | [pattern_trace] 1 27 | [pattern_trace] 0 28 | -------------------------------------------------------------------------------- /examples/rectifier/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.65 (w)1999-2015 BSI 3 | [*] Tue Jan 29 11:11:54 2019 4 | [*] 5 | [dumpfile] "C:\Users\herbstst\Emulation\anasymod\tests\build\dump.vcd" 6 | [dumpfile_mtime] "Tue Jan 29 11:10:35 2019" 7 | [dumpfile_size] 3468 8 | [savefile] "C:\Users\herbstst\Emulation\anasymod\tests\filter\view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-21.591291 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 197 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @8420 18 | top.v_out_probe 19 | @20001 20 | - 21 | @20000 22 | - 23 | - 24 | - 25 | - 26 | - 27 | [pattern_trace] 1 28 | [pattern_trace] 0 29 | -------------------------------------------------------------------------------- /unittests/filter/view_fpga.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Wed Apr 10 03:59:47 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/filter/build/vcd/top_fpga.vcd" 6 | [dumpfile_mtime] "Wed Apr 10 03:58:57 2019" 7 | [dumpfile_size] 244625 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/filter/view_fpga.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-11.683785 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 223 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @10028 18 | tb_i.v_out_probe 19 | @20000 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | [pattern_trace] 1 27 | [pattern_trace] 0 28 | -------------------------------------------------------------------------------- /unittests/multicase/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.65 (w)1999-2015 BSI 3 | [*] Tue Jan 29 11:11:54 2019 4 | [*] 5 | [dumpfile] "C:\Users\herbstst\Emulation\anasymod\tests\build\dump.vcd" 6 | [dumpfile_mtime] "Tue Jan 29 11:10:35 2019" 7 | [dumpfile_size] 3468 8 | [savefile] "C:\Users\herbstst\Emulation\anasymod\tests\filter\view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-21.591291 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 197 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @8420 18 | top.v_out_probe 19 | @20001 20 | - 21 | @20000 22 | - 23 | - 24 | - 25 | - 26 | - 27 | [pattern_trace] 1 28 | [pattern_trace] 0 29 | -------------------------------------------------------------------------------- /unittests/inertial/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.65 (w)1999-2015 BSI 3 | [*] Thu Mar 07 17:34:17 2019 4 | [*] 5 | [dumpfile] "C:\Users\herbstst\Emulation\anasymod\tests\inertial\build\vcd\top_sim.vcd" 6 | [dumpfile_mtime] "Thu Mar 07 17:34:11 2019" 7 | [dumpfile_size] 235334 8 | [savefile] "C:\Users\herbstst\Emulation\anasymod\tests\inertial\view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] 250 256 12 | *-26.509474 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] top. 14 | [treeopen] top.tb_i. 15 | [sst_width] 197 16 | [signals_width] 190 17 | [sst_expanded] 1 18 | [sst_vpaned_height] 153 19 | @28 20 | top.tb_i.in__probe 21 | top.tb_i.out_probe 22 | [pattern_trace] 1 23 | [pattern_trace] 0 24 | -------------------------------------------------------------------------------- /examples/inductor_issue/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Fri May 24 17:19:59 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/inductor_issue/build/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Fri May 24 17:19:52 2019" 7 | [dumpfile_size] 3974 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/inductor_issue/view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-21.984463 750000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] top. 14 | [sst_width] 223 15 | [signals_width] 244 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 153 18 | @8029 19 | top.v_out_probe 20 | @20000 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | @28 28 | top.tb_i.gate_probe 29 | [pattern_trace] 1 30 | [pattern_trace] 0 31 | -------------------------------------------------------------------------------- /unittests/rlc/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // input is voltage square wave 13 | `PWM(0.50, 1e6, in_dig); 14 | `MAKE_CONST_REAL(+1.0, in_hi); 15 | `MAKE_CONST_REAL(-1.0, in_lo); 16 | `ITE_REAL(in_dig, in_hi, in_lo, v_in); 17 | 18 | // output has range range +/- 10 19 | `MAKE_REAL(v_out, 15.0); 20 | 21 | initial begin 22 | $display(`DT_MSDSL); 23 | end 24 | 25 | // filter instantiation 26 | rlc #( 27 | `PASS_REAL(v_in, v_in), 28 | `PASS_REAL(v_out, v_out) 29 | ) rlc_i ( 30 | .v_in(v_in), 31 | .v_out(v_out) 32 | ); 33 | 34 | endmodule 35 | 36 | `default_nettype wire -------------------------------------------------------------------------------- /unittests/one_clock/tb.sv: -------------------------------------------------------------------------------- 1 | module tb; 2 | // emulator I/O 3 | (* dont_touch = "true" *) logic emu_clk; 4 | (* dont_touch = "true" *) logic emu_rst; 5 | (* dont_touch = "true" *) logic [((`DT_WIDTH)-1):0] dt_req; 6 | (* dont_touch = "true" *) logic [((`DT_WIDTH)-1):0] emu_dt; 7 | (* dont_touch = "true" *) logic clk_val; 8 | (* dont_touch = "true" *) logic clk_i; 9 | 10 | // low and high durations 11 | (* dont_touch = "true" *) logic [((`DT_WIDTH)-1):0] t_lo; 12 | (* dont_touch = "true" *) logic [((`DT_WIDTH)-1):0] t_hi; 13 | 14 | // oscillator 15 | osc osc_i ( 16 | .emu_clk(emu_clk), 17 | .emu_rst(emu_rst), 18 | .dt_req(dt_req), 19 | .emu_dt(emu_dt), 20 | .clk_val(clk_val), 21 | .t_lo(t_lo), 22 | .t_hi(t_hi) 23 | ); 24 | endmodule 25 | -------------------------------------------------------------------------------- /examples/inductor_issue/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | 13 | localparam real sw_duty = 0.5; // duty cycle of gate drive 14 | localparam real sw_freq = 1e6; // frequency of gate drive 15 | 16 | `PWM(sw_duty, sw_freq, gate); 17 | 18 | // input is a fixed value 19 | `MAKE_CONST_REAL(1.0, v_in); 20 | 21 | // output has range range +/- 1.5 22 | `MAKE_REAL(v_out, 1.5); 23 | 24 | // filter instantiation 25 | filter #( 26 | `PASS_REAL(v_in, v_in), 27 | `PASS_REAL(v_out, v_out) 28 | ) filter_i ( 29 | .v_in(v_in), 30 | .v_out(v_out), 31 | .sw1(1'b1), 32 | .sw2(gate) 33 | ); 34 | 35 | endmodule 36 | 37 | `default_nettype wire -------------------------------------------------------------------------------- /unittests/rlc/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.65 (w)1999-2015 BSI 3 | [*] Fri Feb 01 13:47:24 2019 4 | [*] 5 | [dumpfile] "C:\Users\herbstst\Emulation\anasymod\tests\build\dump.vcd" 6 | [dumpfile_mtime] "Fri Feb 01 13:46:14 2019" 7 | [dumpfile_size] 49321 8 | [savefile] "C:\Users\herbstst\Emulation\anasymod\tests\rlc\view.gtkw" 9 | [timestart] 0 10 | [size] 1253 584 11 | [pos] -1 -1 12 | *-21.591291 3630000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 197 14 | [signals_width] 118 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 148 17 | @8028 18 | top.v_in_probe 19 | @20001 20 | - 21 | @20000 22 | - 23 | @8028 24 | top.v_out_probe 25 | @20000 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | @8028 33 | top.i_ind_probe 34 | @20000 35 | - 36 | - 37 | - 38 | - 39 | - 40 | - 41 | [pattern_trace] 1 42 | [pattern_trace] 0 43 | -------------------------------------------------------------------------------- /examples/comparator/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Fri Jul 19 15:34:21 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/comparator/build/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Fri Jul 19 15:33:37 2019" 7 | [dumpfile_size] 1196 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/comparator/view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-14.683660 1000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] top. 14 | [sst_width] 223 15 | [signals_width] 118 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 153 18 | @10028 19 | top.in_p_probe 20 | @20000 21 | - 22 | - 23 | @10028 24 | top.in_n_probe 25 | @20001 26 | - 27 | @20000 28 | - 29 | @28 30 | top.tb_i.out_probe 31 | @20000 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | [pattern_trace] 1 39 | [pattern_trace] 0 40 | -------------------------------------------------------------------------------- /anasymod/verilog/calc_emu_time.sv: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1ns/1ps 3 | 4 | `include "msdsl.sv" 5 | 6 | `default_nettype none 7 | 8 | module calc_emu_time #( 9 | parameter integer width=-1, 10 | parameter integer time_width=-1, 11 | parameter real tstop=-1 12 | ) ( 13 | output var logic signed [(time_width-1):0] emu_time, 14 | input wire logic emu_clk, 15 | input wire logic emu_rst 16 | ); 17 | `MAKE_GENERIC_REAL(emu_time_int, 1.1*tstop, time_width); 18 | `COPY_FORMAT_REAL(emu_time_int, emu_time_next); 19 | `COPY_FORMAT_REAL(emu_time_int, emu_dt); 20 | 21 | `ASSIGN_CONST_REAL(0.0000001, emu_dt); 22 | `ADD_INTO_REAL(emu_time_int, emu_dt, emu_time_next); 23 | `MEM_INTO_ANALOG(emu_time_next, emu_time_int, 1'b1, `CLK_MSDSL, `RST_MSDSL, 0); 24 | assign emu_time = emu_time_int; 25 | endmodule 26 | 27 | `default_nettype wire -------------------------------------------------------------------------------- /examples/current_switch/gen.py: -------------------------------------------------------------------------------- 1 | from msdsl import MixedSignalModel, RangeOf, AnalogSignal 2 | from anasymod import ExampleControl 3 | 4 | def main(cap=1e-12, res=600): 5 | ctrl = ExampleControl() 6 | 7 | # define ports 8 | m = MixedSignalModel('current_switch', dt=ctrl.dt) 9 | m.add_digital_input('ctrl') 10 | m.add_analog_input('v_in') 11 | m.add_analog_output('v_out') 12 | 13 | # define the circuit 14 | c = m.make_circuit() 15 | gnd = c.make_ground() 16 | 17 | c.switch('net_v_in', 'net_v_out', m.ctrl, r_on=res, r_off=10e3*res) 18 | c.capacitor('net_v_out', gnd, cap, voltage_range=RangeOf(m.v_out)) 19 | c.voltage('net_v_in', gnd, m.v_in) 20 | 21 | c.add_eqns( 22 | m.v_out == AnalogSignal('net_v_out') 23 | ) 24 | 25 | # write model 26 | ctrl.write_model(m) 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /unittests/bitwise/gen.py: -------------------------------------------------------------------------------- 1 | from msdsl import MixedSignalModel, DigitalOutput, DigitalInput 2 | from anasymod import ExampleControl 3 | 4 | def main(): 5 | ctrl = ExampleControl() 6 | 7 | # create the model 8 | model = MixedSignalModel('bitwise', DigitalInput('a'), DigitalInput('b'), DigitalOutput('a_and_b'), 9 | DigitalOutput('a_or_b'), DigitalOutput('a_xor_b'), DigitalOutput('a_inv'), 10 | DigitalOutput('b_inv'), dt=ctrl.dt) 11 | model.set_this_cycle(model.a_and_b, model.a & model.b) 12 | model.set_this_cycle(model.a_or_b, model.a | model.b) 13 | model.set_this_cycle(model.a_xor_b, model.a ^ model.b) 14 | model.set_this_cycle(model.a_inv, ~model.a) 15 | model.set_this_cycle(model.b_inv, ~model.b) 16 | 17 | # write model 18 | ctrl.write_model(model) 19 | 20 | if __name__ == '__main__': 21 | main() -------------------------------------------------------------------------------- /unittests/enums.py: -------------------------------------------------------------------------------- 1 | class RunTimeEnvs: 2 | """ 3 | Container including enums for supported Run Time Environments. 4 | """ 5 | 6 | nocplusplus = "nocplusplus" 7 | pmmlegacy = "pmmlegacy" 8 | stdsc_gcc_32 = "stdsc_gcc_32" 9 | stdsc_gcc_64 = "stdsc_gcc_64" 10 | stdsc_vc14_32 = "stdsc_vc14_32" 11 | stdsc_vc14_64 = "stdsc_vc14_64" 12 | 13 | class TestClassification: 14 | """ 15 | Container including enums for supported Run Time Environments. 16 | """ 17 | 18 | basic = "basic" 19 | weekend = "weekend" 20 | 21 | 22 | class Target: 23 | """ 24 | Container including enums for supported Targets. 25 | """ 26 | 27 | sim_icarus = "sim_icarus" 28 | sim_vivado = "sim_vivado" 29 | build_vivado = "build_vivado" 30 | emulate_vivado = "emulate_vivado" 31 | sim_xcelium = "sim_xcelium" 32 | 33 | -------------------------------------------------------------------------------- /examples/current_switch/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Fri Jul 19 17:40:45 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/current_switch/build/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Fri Jul 19 17:40:18 2019" 7 | [dumpfile_size] 8305 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/current_switch/view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-10.683929 2295 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] top. 14 | [sst_width] 223 15 | [signals_width] 118 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 153 18 | @28 19 | top.tb_i.ctrl_probe 20 | @10028 21 | top.v_in_probe 22 | @20000 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | @10028 34 | top.v_out_probe 35 | @20001 36 | - 37 | @20000 38 | - 39 | - 40 | [pattern_trace] 1 41 | [pattern_trace] 0 42 | -------------------------------------------------------------------------------- /unittests/buck/view_fpga.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Wed Mar 24 18:52:08 2021 4 | [*] 5 | [dumpfile] "/home/steven/Code/anasymod/unittests/buck/build/fpga/vcd/top_fpga.vcd" 6 | [dumpfile_mtime] "Wed Mar 24 18:50:54 2021" 7 | [dumpfile_size] 1680727 8 | [savefile] "/home/steven/Code/anasymod/unittests/buck/view_fpga.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] 114 162 12 | *-35.131905 101450000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [sst_width] 223 14 | [signals_width] 182 15 | [sst_expanded] 1 16 | [sst_vpaned_height] 153 17 | @8028 18 | trace_port_gen_i.v_out_probe 19 | @20000 20 | - 21 | - 22 | - 23 | @8028 24 | trace_port_gen_i.i_ind_probe 25 | @20000 26 | - 27 | - 28 | - 29 | - 30 | @28 31 | trace_port_gen_i.hs_probe 32 | @29 33 | trace_port_gen_i.ls_probe 34 | [pattern_trace] 1 35 | [pattern_trace] 0 36 | -------------------------------------------------------------------------------- /examples/current_switch_array/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Fri Jul 19 17:40:45 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/current_switch/build/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Fri Jul 19 17:40:18 2019" 7 | [dumpfile_size] 8305 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/current_switch/view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-10.683929 2295 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] top. 14 | [sst_width] 223 15 | [signals_width] 118 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 153 18 | @28 19 | top.tb_i.ctrl_probe 20 | @10028 21 | top.v_in_probe 22 | @20000 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | @10028 34 | top.v_out_probe 35 | @20001 36 | - 37 | @20000 38 | - 39 | - 40 | [pattern_trace] 1 41 | [pattern_trace] 0 42 | -------------------------------------------------------------------------------- /unittests/buck/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Wed Mar 24 18:05:52 2021 4 | [*] 5 | [dumpfile] "/home/steven/Code/anasymod/unittests/buck/build/sim/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Wed Mar 24 18:05:18 2021" 7 | [dumpfile_size] 190863 8 | [savefile] "/home/steven/Code/anasymod/unittests/buck/view.gtkw" 9 | [timestart] 0 10 | [size] 858 452 11 | [pos] -1 -1 12 | *-35.320881 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] top. 14 | [sst_width] 223 15 | [signals_width] 118 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 102 18 | @8028 19 | top.trace_port_gen_i.v_out_probe 20 | @20000 21 | - 22 | - 23 | - 24 | @8028 25 | top.trace_port_gen_i.i_ind_probe 26 | @20000 27 | - 28 | - 29 | - 30 | - 31 | @28 32 | top.trace_port_gen_i.hs_probe 33 | top.trace_port_gen_i.ls_probe 34 | [pattern_trace] 1 35 | [pattern_trace] 0 36 | -------------------------------------------------------------------------------- /anasymod/files.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path 3 | from pathlib import Path 4 | import shutil 5 | 6 | # working with paths 7 | 8 | def get_full_path(path): 9 | return str(Path(path).resolve()) 10 | 11 | def get_sibling(path, sibling): 12 | return str(Path(path).parent / sibling) 13 | 14 | # working with programs 15 | 16 | def which(program, path=None): 17 | return get_full_path(shutil.which(program, path=path)) 18 | 19 | # working with packages 20 | 21 | def anasymod_root(): 22 | return Path(__file__).parent 23 | 24 | def anasymod_header(): 25 | return anasymod_root() / 'verilog' / 'anasymod.sv' 26 | 27 | def get_from_anasymod(*args): 28 | return os.path.join(str(anasymod_root()), *args) 29 | 30 | # working with directories 31 | 32 | def mkdir_p(path): 33 | Path(path).mkdir(parents=True, exist_ok=True) 34 | 35 | def rm_rf(path): 36 | shutil.rmtree(path, ignore_errors=True) 37 | -------------------------------------------------------------------------------- /anasymod/viewer/simvision.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from anasymod.viewer.viewer import Viewer 4 | from anasymod.util import call 5 | 6 | class SimVisionViewer(Viewer): 7 | def view(self): 8 | # build command 9 | if os.path.isfile(self.target.cfg.vcd_path): 10 | cmd = [self.cfg.simvision_config.simvision, '-wave', self.target.cfg.vcd_path] 11 | cmd[1:1] = self.cfg.simvision_config.lsf_opts.split() 12 | # add waveform file if it exists 13 | if self.cfg.simvision_config.svcf_config is not None: 14 | if os.path.isfile(self.cfg.simvision_config.svcf_config): 15 | cmd.extend(['-input', self.cfg.simvision_config.svcf_config]) 16 | 17 | # run command 18 | call(cmd) 19 | else: 20 | raise Exception(f'ERROR: Result file: {self.target.cfg.vcd_path} does not exist; cannot open waveforms!') -------------------------------------------------------------------------------- /examples/rectifier/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // gate drive signal 13 | 14 | `PWM(0.50, 1e6, ctrl); 15 | 16 | // generate square wave voltage 17 | `MAKE_REAL(v_in, 1.0); 18 | always @(*) begin 19 | case (ctrl) 20 | 1'b0: `FORCE_REAL(-1.0, v_in); 21 | 1'b1: `FORCE_REAL(+1.0, v_in); 22 | default: `FORCE_REAL(+1.0, v_in); 23 | endcase 24 | end 25 | 26 | // Output definition 27 | `MAKE_REAL(v_out, 1.5); 28 | 29 | // filter instantiation 30 | filter #( 31 | `PASS_REAL(v_in, v_in), 32 | `PASS_REAL(v_out, v_out) 33 | ) filter_i ( 34 | .v_in(v_in), 35 | .v_out(v_out) 36 | ); 37 | 38 | endmodule 39 | 40 | `default_nettype wire -------------------------------------------------------------------------------- /examples/buck_circuit/view.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Wed Apr 10 04:31:21 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/buck/build/vcd/top_sim.vcd" 6 | [dumpfile_mtime] "Wed Apr 10 04:31:13 2019" 7 | [dumpfile_size] 169661 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/buck/view.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-25.066996 26800000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] top. 14 | [treeopen] top.tb_i. 15 | [sst_width] 223 16 | [signals_width] 182 17 | [sst_expanded] 1 18 | [sst_vpaned_height] 153 19 | @28 20 | top.tb_i.hs_probe 21 | top.tb_i.ls_probe 22 | @8028 23 | top.v_out_probe 24 | @20000 25 | - 26 | - 27 | @8028 28 | top.i_ind_probe 29 | @20000 30 | - 31 | - 32 | @8028 33 | top.v_snub_probe 34 | @20000 35 | - 36 | - 37 | - 38 | [pattern_trace] 1 39 | [pattern_trace] 0 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*.*.*' 7 | jobs: 8 | linux: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | - name: Set up Python 3.7 14 | uses: actions/setup-python@v2 15 | with: 16 | python-version: 3.7 17 | - name: Install dependencies 18 | run: sudo apt-get install iverilog 19 | - name: Run regression test 20 | run: source regress.sh 21 | env: 22 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 23 | - name: Build source distribution 24 | run: python setup.py sdist 25 | - name: Publish source distribution to PyPI 26 | env: 27 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 28 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 29 | run: | 30 | pip install twine 31 | twine upload dist/* 32 | -------------------------------------------------------------------------------- /anasymod/viewer/gtkwave.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from anasymod.viewer.viewer import Viewer 4 | from anasymod.util import call 5 | 6 | class GtkWaveViewer(Viewer): 7 | def view(self, result_file=None): 8 | vcd_path = result_file if result_file is not None else self.target.cfg.vcd_path 9 | 10 | # build command 11 | if os.path.isfile(vcd_path): 12 | cmd = [self.cfg.gtkwave_config.gtkwave, vcd_path] 13 | cmd[1:1] = self.cfg.gtkwave_config.lsf_opts.split() 14 | # add waveform file if it exists 15 | if self.cfg.gtkwave_config.gtkw_config is not None: 16 | if os.path.isfile(self.cfg.gtkwave_config.gtkw_config): 17 | cmd.append(self.cfg.gtkwave_config.gtkw_config) 18 | 19 | # run command 20 | call(cmd) 21 | else: 22 | raise Exception(f'ERROR: Result file: {vcd_path} does not exist; cannot open waveforms!') -------------------------------------------------------------------------------- /examples/buck_circuit/view_fpga.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI 3 | [*] Wed Apr 10 04:40:57 2019 4 | [*] 5 | [dumpfile] "/home/sgherbst/Code/anasymod/tests/buck/build/vcd/top_fpga.vcd" 6 | [dumpfile_mtime] "Wed Apr 10 04:40:10 2019" 7 | [dumpfile_size] 399780 8 | [savefile] "/home/sgherbst/Code/anasymod/tests/buck/view_fpga.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] 49 42 12 | *-14.166062 26800000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] tb_i. 14 | [sst_width] 223 15 | [signals_width] 182 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 153 18 | @28 19 | tb_i.hs_probe 20 | tb_i.ls_probe 21 | @8028 22 | tb_i.v_out_probe 23 | @20000 24 | - 25 | - 26 | @8028 27 | tb_i.i_ind_probe 28 | @20000 29 | - 30 | - 31 | - 32 | - 33 | - 34 | @8028 35 | tb_i.buck_i.v_snub_probe 36 | @20001 37 | - 38 | @20000 39 | - 40 | - 41 | [pattern_trace] 1 42 | [pattern_trace] 0 43 | -------------------------------------------------------------------------------- /unittests/firmware/tb.sv: -------------------------------------------------------------------------------- 1 | `timescale 1s/1ns 2 | 3 | module tb; 4 | logic [7:0] a_in; 5 | logic [7:0] b_in; 6 | logic [7:0] mode_in; 7 | logic [7:0] c_out; 8 | 9 | always @(*) begin 10 | if (mode_in == 0) begin 11 | c_out = a_in + b_in; 12 | end else if (mode_in == 1) begin 13 | c_out = a_in - b_in; 14 | end else if (mode_in == 2) begin 15 | c_out = b_in - a_in; 16 | end else if (mode_in == 3) begin 17 | c_out = a_in * b_in; 18 | end else if (mode_in == 4) begin 19 | c_out = a_in >> b_in; 20 | end else if (mode_in == 5) begin 21 | c_out = a_in << b_in; 22 | end else if (mode_in == 6) begin 23 | c_out = b_in >> a_in; 24 | end else if (mode_in == 7) begin 25 | c_out = b_in << a_in; 26 | end else begin 27 | c_out = 42; 28 | end 29 | end 30 | endmodule 31 | -------------------------------------------------------------------------------- /unittests/custom_firmware/tb.sv: -------------------------------------------------------------------------------- 1 | `timescale 1s/1ns 2 | 3 | module tb; 4 | logic [7:0] a_in; 5 | logic [7:0] b_in; 6 | logic [7:0] mode_in; 7 | logic [7:0] c_out; 8 | 9 | always @(*) begin 10 | if (mode_in == 0) begin 11 | c_out = a_in + b_in; 12 | end else if (mode_in == 1) begin 13 | c_out = a_in - b_in; 14 | end else if (mode_in == 2) begin 15 | c_out = b_in - a_in; 16 | end else if (mode_in == 3) begin 17 | c_out = a_in * b_in; 18 | end else if (mode_in == 4) begin 19 | c_out = a_in >> b_in; 20 | end else if (mode_in == 5) begin 21 | c_out = a_in << b_in; 22 | end else if (mode_in == 6) begin 23 | c_out = b_in >> a_in; 24 | end else if (mode_in == 7) begin 25 | c_out = b_in << a_in; 26 | end else begin 27 | c_out = 42; 28 | end 29 | end 30 | endmodule 31 | -------------------------------------------------------------------------------- /unittests/buck/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // I/O definition 13 | `MAKE_CONST_REAL(5.0, v_in); 14 | `MAKE_REAL(v_out, 10.0); 15 | `MAKE_REAL(i_ind, 20.0); 16 | 17 | // Diode emulation comparison 18 | `MAKE_CONST_REAL(10e-3, ls_thresh); 19 | `GT_REAL(i_ind, ls_thresh, ls_en); 20 | 21 | // High-side signal 22 | `PWM(0.50, 500e3, hs); 23 | 24 | // Low-side signal 25 | logic ls; 26 | assign ls = (~hs) & ls_en; 27 | 28 | // buck instantiation 29 | buck #( 30 | `PASS_REAL(v_in, v_in), 31 | `PASS_REAL(v_out, v_out), 32 | `PASS_REAL(i_ind, i_ind) 33 | ) buck_i ( 34 | .v_in(v_in), 35 | .v_out(v_out), 36 | .i_ind(i_ind), 37 | .hs(hs), 38 | .ls(ls) 39 | ); 40 | 41 | endmodule 42 | 43 | `default_nettype wire -------------------------------------------------------------------------------- /examples/buck_circuit/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | // I/O definition 13 | `MAKE_CONST_REAL(5.0, v_in); 14 | `MAKE_REAL(v_out, 10.0); 15 | `MAKE_REAL(i_ind, 20.0); 16 | 17 | // Diode emulation comparison 18 | `MAKE_CONST_REAL(10e-3, ls_thresh); 19 | `GT_REAL(i_ind, ls_thresh, ls_en); 20 | 21 | // High-side signal 22 | `PWM(0.50, 500e3, hs); 23 | 24 | // Low-side signal 25 | logic ls; 26 | assign ls = (~hs) & ls_en; 27 | 28 | // buck instantiation 29 | buck #( 30 | `PASS_REAL(v_in, v_in), 31 | `PASS_REAL(v_out, v_out), 32 | `PASS_REAL(i_ind, i_ind) 33 | ) buck_i ( 34 | .v_in(v_in), 35 | .v_out(v_out), 36 | .i_ind(i_ind), 37 | .hs(hs), 38 | .ls(ls) 39 | ); 40 | 41 | endmodule 42 | 43 | `default_nettype wire -------------------------------------------------------------------------------- /unittests/inertial/gen.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | from argparse import ArgumentParser 3 | 4 | from msdsl import MixedSignalModel, VerilogGenerator, DigitalInput, DigitalOutput 5 | from anasymod import get_full_path 6 | 7 | def main(): 8 | print('Running model generator...') 9 | 10 | # parse command line arguments 11 | parser = ArgumentParser() 12 | parser.add_argument('-o', '--output', type=str) 13 | parser.add_argument('--dt', type=float, default=0.1e-6) 14 | args = parser.parse_args() 15 | 16 | # create the model 17 | m = MixedSignalModel('inertial', DigitalInput('in_'), DigitalOutput('out'), dt=args.dt) 18 | m.set_this_cycle(m.out, m.inertial_delay(m.in_, tr=42e-6, tf=0e-6)) 19 | 20 | # determine the output filename 21 | filename = os.path.join(get_full_path(args.output), f'{m.module_name}.sv') 22 | print('Model will be written to: ' + filename) 23 | 24 | # generate the model 25 | m.compile_to_file(VerilogGenerator(), filename) 26 | 27 | if __name__ == '__main__': 28 | main() -------------------------------------------------------------------------------- /unittests/tf/gen.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | from argparse import ArgumentParser 3 | 4 | from msdsl import MixedSignalModel, VerilogGenerator, AnalogInput, AnalogOutput 5 | from anasymod import get_full_path 6 | 7 | def main(num=(1e12,), den=(1, 8e5, 1e12,)): 8 | print('Running model generator...') 9 | 10 | # parse command line arguments 11 | parser = ArgumentParser() 12 | parser.add_argument('-o', '--output', type=str) 13 | parser.add_argument('--dt', type=float) 14 | args = parser.parse_args() 15 | 16 | # create the model 17 | model = MixedSignalModel('filter', AnalogInput('v_in'), AnalogOutput('v_out'), dt=args.dt) 18 | model.set_tf(input_=model.v_in, output=model.v_out, tf=(num, den)) 19 | 20 | # determine the output filename 21 | filename = os.path.join(get_full_path(args.output), f'{model.module_name}.sv') 22 | print('Model will be written to: ' + filename) 23 | 24 | # generate the model 25 | model.compile_to_file(VerilogGenerator(), filename) 26 | 27 | if __name__ == '__main__': 28 | main() -------------------------------------------------------------------------------- /examples/current_switch_array/gen.py: -------------------------------------------------------------------------------- 1 | from msdsl import MixedSignalModel, RangeOf, AnalogSignal, sum_op, Deriv 2 | from anasymod import ExampleControl 3 | 4 | def main(cap=1e-12, res=600, n_array=47): 5 | ctrl = ExampleControl() 6 | 7 | # define ports 8 | m = MixedSignalModel('current_switch_array', dt=ctrl.dt) 9 | m.add_digital_input('ctrl', n_array) 10 | m.add_analog_input('v_in') 11 | m.add_analog_output('v_out', init=0) # can change initial value if desired 12 | 13 | # find number of zeros 14 | m.immediate_assign('n_on', n_array - sum_op([m.ctrl[k] for k in range(m.ctrl.width)])) 15 | 16 | # compute the unit current 17 | m.immediate_assign('i_unit', (m.v_in - m.v_out)/res) 18 | 19 | # compute the array current 20 | m.immediate_assign('i_array', m.n_on * m.i_unit) 21 | 22 | # define the voltage update on the cap 23 | m.next_cycle_assign(m.v_out, m.v_out + m.i_array / (n_array * cap) * ctrl.dt) 24 | 25 | # write model 26 | ctrl.write_model(m) 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /anasymod/generators/xsct.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | import re 3 | import shutil 4 | from pathlib import Path 5 | 6 | from anasymod.util import call 7 | from anasymod.generators.codegen import CodeGenerator 8 | from anasymod.config import EmuConfig 9 | 10 | class XSCTTCLGenerator(CodeGenerator): 11 | """ 12 | Class for generating TCL scripts for XSCT 13 | """ 14 | 15 | def __init__(self, pcfg: EmuConfig,xsct=None, version=None, 16 | version_year=None, version_number=None, 17 | xsct_install_dir=None): 18 | super().__init__() 19 | 20 | self.pcfg = pcfg 21 | self._xsct = self.pcfg.xsct_config.xsct 22 | 23 | def run(self, filename=r'run.tcl', err_str=None): 24 | # write the TCL script 25 | tcl_script = Path(self.pcfg.build_root).resolve() / filename 26 | self.write_to_file(tcl_script) 27 | 28 | # assemble the command 29 | cmd = [str(self.pcfg.xsct_config.xsct), str(tcl_script)] 30 | 31 | # run the script 32 | call(args=cmd, err_str=err_str) 33 | -------------------------------------------------------------------------------- /anasymod/structures/signal_base.py: -------------------------------------------------------------------------------- 1 | class Signal(): 2 | def __init__(self, abs_path: str, delimiter='.'): 3 | """ 4 | Class for storing signal information, that will be later used to generate HDL code related to signals. 5 | :param abs_path: Absolute path to the defined signal, this can also only be the name itself, in case it will 6 | not be used for a connection via abs path later 7 | :param delimiter: Delimiter to separate the signal's abs path 8 | """ 9 | self.delimiter = delimiter 10 | # Separate the signal's abs path 11 | signal_hier = abs_path.split(self.delimiter) 12 | 13 | # Check if an abs path was actually provided or only the signal name 14 | if len(signal_hier) == 1: 15 | # Only signal name was given 16 | self.name = ''.join(signal_hier) 17 | self.abs_path = None 18 | elif len(signal_hier) > 1: 19 | # Abs path to signal was provided 20 | self.name = signal_hier[-1] 21 | self.abs_path = abs_path -------------------------------------------------------------------------------- /unittests/rc/gen.py: -------------------------------------------------------------------------------- 1 | from math import exp 2 | from pathlib import Path 3 | from argparse import ArgumentParser 4 | from msdsl import MixedSignalModel, VerilogGenerator 5 | 6 | def main(): 7 | print('Running model generator...') 8 | 9 | # parse command line arguments 10 | parser = ArgumentParser() 11 | parser.add_argument('-o', '--output', type=str, default='build') 12 | parser.add_argument('--dt', type=float, default=0.1e-6) 13 | parser.add_argument('--tau', type=float, default=1.0e-6) 14 | a = parser.parse_args() 15 | 16 | # create the model 17 | m = MixedSignalModel('model', dt=a.dt) 18 | m.add_analog_input('v_in') 19 | m.add_analog_output('v_out') 20 | 21 | # apply dynamics 22 | m.set_next_cycle(m.v_out, m.v_out*exp(-a.dt/a.tau) + m.v_in*(1-exp(-a.dt/a.tau))) 23 | 24 | # determine the output filename 25 | filename = Path(a.output).resolve() / f'{m.module_name}.sv' 26 | print(f'Model will be written to: {filename}') 27 | 28 | # generate the model 29 | m.compile_to_file(VerilogGenerator(), filename) 30 | 31 | if __name__ == '__main__': 32 | main() 33 | -------------------------------------------------------------------------------- /examples/current_switch_array/tb.sv: -------------------------------------------------------------------------------- 1 | // Steven Herbst 2 | // sherbst@stanford.edu 3 | 4 | `timescale 1ns/1ps 5 | 6 | `include "svreal.sv" 7 | `include "msdsl.sv" 8 | 9 | `default_nettype none 10 | 11 | module tb; 12 | localparam integer n_array=47; 13 | 14 | // analog inputs 15 | `MAKE_CONST_REAL(1.3, v_in); 16 | 17 | // analog outputs 18 | `MAKE_REAL(v_out, 5.0); 19 | 20 | // control signal 21 | logic [n_array-1:0] ctrl; 22 | 23 | // comparator instantiation 24 | current_switch_array #( 25 | `PASS_REAL(v_in, v_in), 26 | `PASS_REAL(v_out, v_out) 27 | ) current_switch_array_i ( 28 | .v_in(v_in), 29 | .ctrl(ctrl), 30 | .v_out(v_out) 31 | ); 32 | 33 | // main stimulus logic 34 | integer i, j; 35 | initial begin 36 | ctrl = {n_array{1'b1}}; 37 | for (i=0; i> 1; 42 | end 43 | $finish; 44 | end 45 | 46 | endmodule 47 | 48 | `default_nettype wire -------------------------------------------------------------------------------- /anasymod/structures/port_base.py: -------------------------------------------------------------------------------- 1 | from anasymod.structures.signal_base import Signal 2 | from anasymod.enums import PortDir 3 | 4 | class Port(): 5 | """ 6 | This is the base class for port generation. 7 | """ 8 | def __init__(self, name, width, direction=None, **kwargs): 9 | self.name = name 10 | self.width = width 11 | self.connection = None 12 | self.direction = direction 13 | self.__init_value = kwargs['init_value'] if 'init_value' in kwargs else None 14 | 15 | @property 16 | def init_value(self): 17 | if self.direction == PortDir.OUT: 18 | return self.__init_value 19 | 20 | def connect(self, signal: Signal): 21 | """ 22 | Connects a signal to the port. 23 | """ 24 | self.connection = signal.name 25 | 26 | class PortIN(Port): 27 | def __init__(self, name, width=1): 28 | super().__init__(name=name, width=width, direction=PortDir.IN) 29 | 30 | class PortOUT(Port): 31 | def __init__(self, name, width=1, direction=PortDir.OUT, init_value=None): 32 | super().__init__(name=name, width=width) -------------------------------------------------------------------------------- /anasymod/verilog/time_manager.sv: -------------------------------------------------------------------------------- 1 | module time_manager #( 2 | parameter integer n=-1, 3 | parameter integer width=-1, 4 | parameter integer time_width=-1 5 | ) ( 6 | input wire logic signed [(width-1):0] dt_req [n], 7 | output wire logic signed [(width-1):0] emu_dt, 8 | output var logic signed [(time_width-1):0] emu_time, 9 | input wire logic emu_clk, 10 | input wire logic emu_rst 11 | ); 12 | // create array of intermediate results and assign the endpoints 13 | wire logic signed [(width-1):0] dt_arr [n]; 14 | assign dt_arr[0] = dt_req[0]; 15 | assign emu_dt = dt_arr[n-1]; 16 | 17 | // assign intermediate results 18 | genvar k; 19 | generate 20 | for (k=1; k\tc=%0d\t(expct=%0d)", 17 | a, b, mode, c_out, expct); 18 | if (!(c_out === expct)) begin 19 | $error("Output mismatch."); 20 | end 21 | #(10e-9*1s); 22 | endtask 23 | 24 | initial begin 25 | // wait for reset to finish 26 | wait_emu_reset(); 27 | 28 | // try out different operating modes 29 | run_test(12, 34, 0, 46); 30 | run_test(45, 10, 1, 35); 31 | run_test(10, 44, 2, 34); 32 | run_test(3, 7, 3, 21); 33 | run_test(9, 1, 4, 4); 34 | run_test(9, 1, 5, 18); 35 | run_test(2, 32, 6, 8); 36 | run_test(3, 3, 7, 24); 37 | run_test(56, 78, 8, 42); 38 | 39 | // end simulation 40 | $finish; 41 | end 42 | endmodule -------------------------------------------------------------------------------- /unittests/custom_firmware/sim_ctrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module sim_ctrl ( 4 | output reg [7:0] a_in, 5 | output reg [7:0] b_in, 6 | output reg [7:0] mode_in, 7 | input [7:0] c_out 8 | ); 9 | `include "anasymod.sv" 10 | 11 | task run_test(input [7:0] a, input [7:0] b, input [7:0] mode, input [7:0] expct); 12 | a_in = a; 13 | b_in = b; 14 | mode_in = mode; 15 | #(10e-9*1s); 16 | $display("a=%0d,\tb=%0d,\tmode=%0d\t->\tc=%0d\t(expct=%0d)", 17 | a, b, mode, c_out, expct); 18 | if (!(c_out === expct)) begin 19 | $error("Output mismatch."); 20 | end 21 | #(10e-9*1s); 22 | endtask 23 | 24 | initial begin 25 | // wait for reset to finish 26 | wait_emu_reset(); 27 | 28 | // try out different operating modes 29 | run_test(12, 34, 0, 46); 30 | run_test(45, 10, 1, 35); 31 | run_test(10, 44, 2, 34); 32 | run_test(3, 7, 3, 21); 33 | run_test(9, 1, 4, 4); 34 | run_test(9, 1, 5, 18); 35 | run_test(2, 32, 6, 8); 36 | run_test(3, 3, 7, 24); 37 | run_test(56, 78, 8, 42); 38 | 39 | // end simulation 40 | $finish; 41 | end 42 | endmodule -------------------------------------------------------------------------------- /examples/rectifier/gen.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | from argparse import ArgumentParser 3 | 4 | from msdsl import MixedSignalModel, VerilogGenerator 5 | from anasymod import get_full_path 6 | 7 | def main(tau=1e-6): 8 | print('Running model generator...') 9 | 10 | # parse command line arguments 11 | parser = ArgumentParser() 12 | parser.add_argument('-o', '--output', type=str) 13 | parser.add_argument('--dt', type=float) 14 | args = parser.parse_args() 15 | 16 | # create the model 17 | m = MixedSignalModel('filter', dt=args.dt) 18 | 19 | m.add_analog_input('v_in') 20 | m.add_analog_output('v_out') 21 | 22 | c = m.make_circuit() 23 | gnd = c.make_ground() 24 | 25 | c.voltage('net_v_in', gnd, m.v_in) 26 | c.diode('net_v_in', 'net_v_x', vf=0) 27 | c.resistor('net_v_x', 'net_v_out', 1e3) 28 | v_out = c.capacitor('net_v_out', gnd, 1e-9, voltage_range=1.5) 29 | 30 | m.set_this_cycle(m.v_out, v_out) 31 | 32 | # determine the output filename 33 | filename = os.path.join(get_full_path(args.output), f'{m.module_name}.sv') 34 | print('Model will be written to: ' + filename) 35 | 36 | # generate the model 37 | m.compile_to_file(VerilogGenerator(), filename) 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /anasymod/sim/xcelium.make_target: -------------------------------------------------------------------------------- 1 | 2 | #*********************************************************** 3 | # E X E C U T E target for anasymod in Inicio environment 4 | # - compile 5 | # - elaborate 6 | # - run 7 | # 8 | # The return status of "xrun" is stored in a file called .ifxxcelium.xrun_status.txt. 9 | # The file name must not be modified and the file must not be removed 10 | # or modified manually. 11 | #----------------------------------------------------------- 12 | .PHONY: inicio 13 | inicio: 14 | @echo "[INFO] make: execute in inicio environment" 15 | @echo "[INFO] make: running xrun..." 16 | @echo "[INFO] make: ... with following command line options: $(CMD_LINE_ARGS)" 17 | @echo "[INFO] make: ... and following dynamic use modes: $(USE_MODES)" 18 | @\rm -f .ifxxcelium.xrun_status.txt 19 | ifndef DEBUSSYROOT 20 | ifeq (fsdb, $(filter fsdb, $(USE_MODES))) 21 | $(error Verdi is not properly configured; please check your project configuration) 22 | endif 23 | endif 24 | $(REINVOKE_PROTECTION) xrun \ 25 | -cdslib $(ENV_DIR)/cds.lib \ 26 | -hdlvar $(ENV_DIR)/hdl.var \ 27 | -xmlibdirname $(XCELIUM_D) \ 28 | $(CMD_LINE_ARGS); echo $$? > .ifxxcelium.xrun_status.txt 29 | @exit `cat .ifxxcelium.xrun_status.txt` 30 | @echo "[INFO] make: execute done" 31 | -------------------------------------------------------------------------------- /anasymod/generators/codegen.py: -------------------------------------------------------------------------------- 1 | class CodeGenerator: 2 | def __init__(self, tab_string: str=None, line_ending='\n'): 3 | # save settings 4 | self.tab_string = tab_string if tab_string is not None else ' ' 5 | self.line_ending = line_ending if line_ending is not None else '\n' 6 | 7 | # initialize variables 8 | self.tab_level = 0 9 | self.text = '' 10 | 11 | def write(self, line): 12 | self.text += line 13 | 14 | def writeln(self, line=''): 15 | self.write(self.tab_level * self.tab_string + line + self.line_ending) 16 | 17 | def reset(self): 18 | self.text = '' 19 | 20 | def use_templ(self, template): 21 | self.write(template.render()) 22 | 23 | def write_to_file(self, filename): 24 | with open(filename, 'w') as f: 25 | f.write(self.text) 26 | self.reset() 27 | 28 | def read_from_file(self, filename): 29 | with open(filename, 'r') as f: 30 | self.text += f.read() 31 | 32 | def dump(self): 33 | return self.text 34 | 35 | def indent(self, quantity=1): 36 | self.tab_level += (1 * quantity) 37 | 38 | def dedent(self, quantity=1): 39 | self.tab_level -= (1 * quantity) 40 | assert self.tab_level >= 0 41 | 42 | -------------------------------------------------------------------------------- /unittests/filter/my_filter.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | from argparse import ArgumentParser 3 | 4 | from msdsl import MixedSignalModel, VerilogGenerator, Deriv 5 | from anasymod import get_full_path 6 | 7 | class Filter(MixedSignalModel): 8 | def __init__(self, name='filter', res=1e3, cap=1e-9, dt=0.1e-6): 9 | # call the super constructor 10 | super().__init__(name, dt=dt) 11 | 12 | # define IOs 13 | self.add_analog_input('v_in') 14 | self.add_analog_output('v_out') 15 | 16 | # define dynamics 17 | self.add_eqn_sys([ 18 | Deriv(self.v_out) == (self.v_in - self.v_out) / (res*cap) 19 | ]) 20 | 21 | def main(): 22 | print('Running model generator...') 23 | 24 | # parse command line arguments 25 | parser = ArgumentParser() 26 | parser.add_argument('-o', '--output', type=str) 27 | parser.add_argument('--dt', type=float) 28 | args = parser.parse_args() 29 | 30 | # create the model 31 | model = Filter(dt=args.dt) 32 | 33 | # determine the output filename 34 | filename = os.path.join(get_full_path(args.output), f'{model.module_name}.sv') 35 | print('Model will be written to: ' + filename) 36 | 37 | # generate the model 38 | model.compile_to_file(VerilogGenerator(), filename) 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /anasymod/probe_config.py: -------------------------------------------------------------------------------- 1 | class ProbeConfig: 2 | def __init__(self, probe_cfg_path): 3 | # Read Probe Config file 4 | with (open(probe_cfg_path, "r")) as cf: 5 | config = cf.readlines() 6 | 7 | prefixes = [r"ANALOG:", r"ANALOG_EXPONENT:", r"ANALOG_WIDTH:", r"TIME:", r"TIME_EXPONENT:", r"TIME_WIDTH:", r"RESET:", r"SB:", r"MB:", r"MB_WIDTH:"] 8 | # clean and remove prefixes 9 | signals = [] 10 | for signal, prefix in zip(config, prefixes): 11 | signals.append(signal.strip(prefix).strip().split()) 12 | 13 | self.analog_signals = [] 14 | for name, width, exponent in zip(signals[0], signals[2], signals[1]): 15 | self.analog_signals.append((name, width, exponent)) 16 | 17 | self.time_signal = [] 18 | for name,width, exponent in zip(signals[3], signals[5], signals[4]): 19 | self.time_signal.append((name, width, exponent)) 20 | 21 | self.reset_signal = [] 22 | for name,width, exponent in zip(signals[6], [r"1"], [None]): 23 | self.reset_signal.append((name, width, exponent)) 24 | 25 | self.digital_signals = [] 26 | for name in signals[7]: 27 | self.digital_signals.append((name, r"1", None)) 28 | 29 | for name, width in zip(signals[8], signals[9]): 30 | self.digital_signals.append((name, width, None)) 31 | 32 | -------------------------------------------------------------------------------- /anasymod/verilog/gen_emu_clks.sv: -------------------------------------------------------------------------------- 1 | module gen_emu_clks #( 2 | parameter integer n=2 3 | ) ( 4 | (* dont_touch="true" *) input wire logic emu_clk_2x, 5 | (* dont_touch="true" *) output wire logic emu_clk, 6 | (* dont_touch="true" *) input wire logic clk_vals [n], 7 | (* dont_touch="true" *) output wire logic clks [n] 8 | ); 9 | 10 | // generate emu_clk 11 | logic emu_clk_unbuf = 0; 12 | always @(posedge emu_clk_2x) begin 13 | emu_clk_unbuf <= ~emu_clk_unbuf; 14 | end 15 | `ifndef SIMULATION_MODE_MSDSL 16 | BUFG buf_emu_clk (.I(emu_clk_unbuf), .O(emu_clk)); 17 | `else 18 | assign emu_clk = emu_clk_unbuf; 19 | `endif 20 | 21 | // generate other clocks 22 | logic clk_unbufs [n]; 23 | genvar k; 24 | generate 25 | for (k=0; k to specify the simulator (sim_icarus, sim_vivado, etc.) 28 | # --classification to select which tests are run (basic, weekend, etc.) 29 | pytest --cov-report=xml -v -r s -s \ 30 | --cov=anasymod --target=$ANASYMOD_TARGET unittests 31 | 32 | # if we're on the FPGA server, then run some tests on the FPGA board 33 | # note that --cov-append is used so that we added to the previously 34 | # collected coverage data 35 | if [[ -n "${FPGA_SERVER}" ]]; then 36 | pytest --cov-report=xml --cov-append -v -r s -s \ 37 | --cov=anasymod --target=emulate_vivado \ 38 | unittests/basic_sim/test_basic_sim.py::TestBasicSIM::test_firmware \ 39 | unittests/basic_sim/test_basic_sim.py::TestBasicSIM::test_custom_firmware \ 40 | unittests/basic_sim/test_basic_sim.py::TestBasicSIM::test_rc 41 | fi 42 | 43 | # upload coverage information 44 | curl -s https://codecov.io/bash | bash 45 | -------------------------------------------------------------------------------- /.buildkite/pipeline.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - label: "test" 3 | command: | 4 | # set up environment 5 | source /cad/modules/tcl/init/bash 6 | module load base xcelium/19.03.003 7 | export ANASYMOD_TARGET=sim_xcelium 8 | printenv 9 | 10 | # set up Python environment 11 | /usr/local/miniconda/bin/python3.7 -m venv venv 12 | source venv/bin/activate 13 | 14 | # run regression script 15 | source regress.sh 16 | timeout_in_minutes: 60 17 | agents: 18 | fault2: "true" 19 | - label: "test_emu" 20 | command: | 21 | # set up environment 22 | source /etc/environment 23 | export FPGA_SERVER=1 24 | export ANASYMOD_TARGET=sim_vivado 25 | printenv 26 | 27 | # set up Python environment 28 | python3.7 -m venv venv 29 | source venv/bin/activate 30 | 31 | # update the board name to match what is 32 | # available on the regression server 33 | sed -i 's/PYNQ_Z1/ZC702/g' unittests/*/prj.yaml 34 | 35 | # run regression script 36 | source regress.sh 37 | artifact_paths: 38 | - "unittests/*/build/*/prj/prj.runs/*/*.bit" 39 | - "unittests/*/build/*/prj/prj.runs/*/*.ltx" 40 | - "unittests/*/build/*/prj/prj.runs/*/*.log" 41 | - "unittests/*/build/*/prj/prj.sim/*/behav/xsim/*.log" 42 | - "unittests/*/build/*/prj/prj.sim/*/behav/xsim/*.sh" 43 | - "unittests/*/build/*/prj/prj.runs/*/*.xsa" 44 | - "unittests/*/build/*/prj/prj.runs/*/ps7_init.tcl" 45 | - "unittests/*/build/*/prj/prj.sdk/*/*/*.elf" 46 | - "unittests/*/build/*/*.tcl" 47 | - "unittests/*/prj.y*ml" 48 | timeout_in_minutes: 60 49 | agents: 50 | fpga_verif: "true" 51 | -------------------------------------------------------------------------------- /unittests/function/gen.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from pathlib import Path 3 | from argparse import ArgumentParser 4 | from msdsl import MixedSignalModel, VerilogGenerator 5 | 6 | def myfunc(x): 7 | # clip input 8 | x = np.clip(x, -np.pi, +np.pi) 9 | # apply function 10 | return np.sin(x) 11 | 12 | def gen_model(order, numel, build_dir): 13 | # settings: 14 | # order=0, numel=512 => rms_error <= 0.0105 15 | # order=1, numel=128 => rms_error <= 0.000318 16 | # order=2, numel= 32 => rms_error <= 0.000232 17 | 18 | # create mixed-signal model 19 | m = MixedSignalModel('model', build_dir=build_dir) 20 | m.add_analog_input('in_') 21 | m.add_analog_output('out') 22 | 23 | # create function 24 | real_func = m.make_function(myfunc, domain=[-np.pi, +np.pi], 25 | order=order, numel=numel) 26 | 27 | # apply function 28 | m.set_from_sync_func(m.out, real_func, m.in_) 29 | 30 | # write the model 31 | return m.compile_to_file(VerilogGenerator()) 32 | 33 | def main(): 34 | print('Running model generator...') 35 | 36 | # parse command line arguments 37 | parser = ArgumentParser() 38 | parser.add_argument('-o', '--output', type=str, default='build') 39 | parser.add_argument('--dt', type=float, default=0.1e-6) 40 | parser.add_argument('--order', type=int, default=1) 41 | parser.add_argument('--numel', type=int, default=128) 42 | 43 | # parse arguments 44 | args = parser.parse_args() 45 | 46 | # call the model generator 47 | build_dir = Path(args.output).resolve() 48 | gen_model(order=args.order, numel=args.numel, build_dir=build_dir) 49 | 50 | if __name__ == '__main__': 51 | main() 52 | -------------------------------------------------------------------------------- /anasymod/sim/vivado.py: -------------------------------------------------------------------------------- 1 | import re 2 | from anasymod.sim.sim import Simulator 3 | from anasymod.generators.vivado import VivadoTCLGenerator 4 | 5 | class VivadoSimulator(Simulator): 6 | def simulate(self): 7 | # set up the simulation commands 8 | v = VivadoTCLGenerator(target=self.target) 9 | 10 | # create a new project 11 | v.create_project(project_name=self.cfg.vivado_config.project_name, 12 | project_directory=self.target.project_root, 13 | force=True) 14 | 15 | # add all source files to the project (including header files) 16 | v.add_project_sources(content=self.target.content) 17 | 18 | # define the top module 19 | v.set_property('top', f"{{{self.target.cfg.top_module}}}", '[get_filesets {sim_1 sources_1}]') 20 | 21 | # set define variables 22 | v.add_project_defines(content=self.target.content, fileset='[get_filesets {sim_1 sources_1}]') 23 | 24 | # add include directories 25 | v.add_include_dirs(content=self.target.content, objects='[get_filesets {sim_1 sources_1}]') 26 | 27 | # if desired, treat Verilog (*.v) files as SystemVerilog (*.sv) 28 | if self.target.prj_cfg.cfg.treat_v_as_sv: 29 | v.writeln('set_property file_type SystemVerilog [get_files -filter {FILE_TYPE == Verilog}]') 30 | 31 | # launch the simulation 32 | v.set_property('{xsim.simulate.runtime}', '{-all}', '[get_fileset sim_1]') 33 | v.writeln('launch_simulation') 34 | 35 | # add any additional user-supplied flags 36 | for flag in self.flags: 37 | v.writeln(str(flag)) 38 | 39 | # run the simulation 40 | v.run(filename='vivado_sim.tcl', err_str=re.compile('^(Error|Fatal):')) 41 | -------------------------------------------------------------------------------- /anasymod/verilog/regmap.sv: -------------------------------------------------------------------------------- 1 | module sync #( 2 | parameter integer n=1, 3 | parameter integer depth=2 4 | ) ( 5 | input [n-1:0] in, 6 | output [n-1:0] out, 7 | input clk 8 | ); 9 | 10 | reg [n-1:0] hist [depth+1]; 11 | 12 | assign hist[0] = in; 13 | assign out = hist[depth]; 14 | 15 | genvar i; 16 | generate 17 | for (i=0; i=0.2.7', 16 | 'msdsl>=0.3.7', 17 | 'jinja2', 18 | 'pyvcd', 19 | 'pyserial', 20 | 'PyYAML', 21 | 'si-prefix' 22 | ] 23 | if os.name == 'nt': 24 | install_requires += ['wexpect>=3.3.0'] 25 | else: 26 | install_requires += ['pexpect'] 27 | 28 | setup( 29 | name=name, 30 | version=version, 31 | description=DESCRIPTION, 32 | long_description=LONG_DESCRIPTION, 33 | long_description_content_type='text/markdown', 34 | keywords = ['analog', 'mixed-signal', 'mixed signal', 'vivado', 35 | 'xcelium', 'iverilog', 'icarus-verilog', 'icarus verilog', 36 | 'generator', 'verilog', 'system-verilog', 'system verilog', 37 | 'emulation', 'fpga'], 38 | packages=find_packages(), 39 | entry_points = { 40 | 'console_scripts': [ 41 | 'anasymod=anasymod.analysis:main' 42 | ] 43 | }, 44 | install_requires=install_requires, 45 | license='BSD 3-Clause "New" or "Revised" License', 46 | url=f'https://github.com/sgherbst/{name}', 47 | author='Gabriel Rutsch, Steven Herbst, Shivani Saravanan', 48 | author_email='gabriel.rutsch@infineon.com', 49 | python_requires='>=3.7', 50 | download_url = f'https://github.com/sgherbst/{name}/archive/v{version}.tar.gz', 51 | classifiers=[ 52 | 'Development Status :: 3 - Alpha', 53 | 'Intended Audience :: Developers', 54 | 'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', 55 | 'License :: OSI Approved :: BSD License', 56 | f'Programming Language :: Python :: 3.7' 57 | ], 58 | include_package_data=True, 59 | zip_safe=False 60 | ) 61 | -------------------------------------------------------------------------------- /anasymod/sim_ctrl/console_print.py: -------------------------------------------------------------------------------- 1 | # Terminal formatting codes adapted from http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#8-colors 2 | 3 | import os 4 | 5 | COLOR_CODES = dict( 6 | black = '\x1b[30m', 7 | red = '\x1b[31m', 8 | green = '\x1b[32m', 9 | yellow = '\x1b[33m', 10 | blue = '\x1b[34m', 11 | magenta = '\x1b[35m', 12 | cyan = '\x1b[36m', 13 | white = '\x1b[37m', 14 | bright = '\x1b[1m', 15 | reset = '\x1b[0m', 16 | ) 17 | 18 | def cprint(s, *args, color=None, bold=None, **kwargs): 19 | # set defaults 20 | if bold is None: 21 | bold = color is not None 22 | 23 | # build up the string to print 24 | to_print = f'{s}' 25 | if bold: 26 | to_print = COLOR_CODES['bright'] + to_print 27 | if color is not None: 28 | to_print = COLOR_CODES[color.lower()] + to_print 29 | if bold or color is not None: 30 | to_print += COLOR_CODES['reset'] 31 | 32 | # print the string 33 | print(to_print, *args, **kwargs) 34 | 35 | def cprint_announce(title, text, color=None, bold=None): 36 | if os.name != 'nt': 37 | cprint(title, color=color, bold=bold, end='') 38 | else: 39 | print(title) 40 | print(text) 41 | 42 | def cprint_block_start(title, color=None, bold=None): 43 | if os.name != 'nt': 44 | cprint(f'<{title}>', color=color, bold=bold) 45 | else: 46 | print(f'<{title}>') 47 | 48 | def cprint_block_end(title, color=None, bold=None): 49 | if os.name != 'nt': 50 | cprint(f'', color=color, bold=bold) 51 | else: 52 | print(f'<{title}>') 53 | 54 | def cprint_block(str_list, title, color=None, bold=None): 55 | # don't print out anything if the string list has zero length 56 | if len(str_list) == 0: 57 | return 58 | 59 | # otherwise print out the text with the start and end indicated 60 | cprint_block_start(title, color=color, bold=bold) 61 | for s in str_list: 62 | print(str(s).rstrip()) 63 | cprint_block_end(title, color=color, bold=bold) -------------------------------------------------------------------------------- /anasymod/templates/ila.py: -------------------------------------------------------------------------------- 1 | from anasymod.templates.generic_ip import TemplGenericIp 2 | from anasymod.util import next_pow_2 3 | from anasymod.targets import FPGATarget 4 | 5 | class TemplILA(TemplGenericIp): 6 | def __init__(self, target: FPGATarget, depth=4096): 7 | # set defaults 8 | scfg = target.str_cfg 9 | 10 | # Sanity checking for ILA depth 11 | assert next_pow_2(depth) == depth, 'The ILA depth must be a power of 2.' 12 | assert depth >= 1024, 'The ILA depth must be at least 1024.' 13 | 14 | self.inst_name = target.prj_cfg.vivado_config.ila_inst_name 15 | 16 | self.width_ila_clk = '1' 17 | self.conn_ila_clk = target.str_cfg.emu_clk.name 18 | 19 | props = {} 20 | 21 | # set the number samples per signal 22 | props['CONFIG.C_DATA_DEPTH'] = str(depth) 23 | 24 | # add a pipelined input to reduce burden on timing closure 25 | props['CONFIG.C_INPUT_PIPE_STAGES'] = '1' 26 | 27 | # enable capture control 28 | props['CONFIG.C_EN_STRG_QUAL'] = 'true' 29 | 30 | # two comparators per probe are recommended when using capture control (per UG908, p 40) 31 | props['CONFIG.ALL_PROBE_SAME_MU_CNT'] = '2' 32 | 33 | # specify all signals to be probed 34 | signals = (scfg.digital_probes + scfg.analog_probes + [target.str_cfg.time_probe] + 35 | [target.str_cfg.dec_cmp]) 36 | print(f"Signals: {[f'{signal.name}' for signal in signals]}") 37 | 38 | # Set number of probes in total 39 | props['CONFIG.C_NUM_OF_PROBES'] = str(len(signals)) 40 | 41 | for k, signal in enumerate(signals): 42 | # Add depth for ila signal 43 | props[f'CONFIG.C_PROBE{k}_WIDTH'] = str(signal.width) 44 | 45 | super().__init__(ip_name='ila', props=props, ip_dir=target.ip_dir) 46 | 47 | 48 | def main(): 49 | print(TemplILA(target=FPGATarget(prj_cfg=EmuConfig(root='test', cfg_file=''))).render()) 50 | 51 | if __name__ == "__main__": 52 | main() -------------------------------------------------------------------------------- /unittests/function/sim_ctrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | `include "svreal.sv" 3 | 4 | module sim_ctrl #( 5 | `DECL_REAL(in_), 6 | `DECL_REAL(out) 7 | ) ( 8 | `OUTPUT_REAL(in_), 9 | `INPUT_REAL(out) 10 | ); 11 | `include "anasymod.sv" 12 | 13 | // parameters 14 | localparam real m_pi = 3.1415926535; 15 | localparam real err_tol = 0.000318; 16 | 17 | // wire input 18 | real in_int; 19 | assign `FORCE_REAL(in_int, in_); 20 | 21 | // wire output 22 | real out_int; 23 | assign out_int = `TO_REAL(out); 24 | 25 | // clipping to range 26 | function real clip(input real x, input real min, input real max); 27 | if (x < min) begin 28 | clip = min; 29 | end else if (x > max) begin 30 | clip = max; 31 | end else begin 32 | clip = x; 33 | end 34 | endfunction 35 | 36 | // run simulation 37 | real expct, sum_err_sqrd, rms_err; 38 | integer n_samp; 39 | initial begin 40 | // wait for emulator reset to complete 41 | wait_emu_reset(); 42 | 43 | // walk through simulation values 44 | sum_err_sqrd = 0.0; 45 | n_samp = 0; 46 | for (in_int=-1.2*m_pi; in_int<=+1.2*m_pi; in_int=in_int+0.05) begin 47 | // wait until next clock cycle (and then a little bit) 48 | wait_emu_cycle(); 49 | 50 | // compute expected output 51 | expct = $sin(clip(in_int, -m_pi, +m_pi)); 52 | // print simulation state 53 | $display("in_int: %0f, out_int: %0f, expct: %0f", in_int, out_int, expct); 54 | // accumulate error 55 | sum_err_sqrd = sum_err_sqrd + ((expct - out_int)**2); 56 | n_samp = n_samp + 1; 57 | end 58 | 59 | // check result 60 | rms_err = $sqrt((1.0/n_samp)*sum_err_sqrd); 61 | $display("RMS error: %0f", rms_err); 62 | if (!(rms_err <= err_tol)) begin 63 | $error("RMS error is too high."); 64 | end 65 | 66 | // end simulation 67 | $finish; 68 | end 69 | endmodule 70 | -------------------------------------------------------------------------------- /anasymod/sim_ctrl/vio_ctrlinfra.py: -------------------------------------------------------------------------------- 1 | from anasymod.sim_ctrl.ctrlinfra import ControlInfrastructure 2 | from anasymod.structures.module_viosimctrl import ModuleVIOSimCtrl 3 | from anasymod.sources import VerilogSource 4 | from anasymod.structures.structure_config import StructureConfig 5 | from anasymod.templates.vio_wiz import TemplVIO 6 | 7 | class VIOControlInfrastructure(ControlInfrastructure): 8 | def __init__(self, prj_cfg, plugin_includes): 9 | super().__init__(prj_cfg=prj_cfg, plugin_includes=plugin_includes) 10 | 11 | # Initialize internal variables 12 | 13 | def gen_ctrlwrapper(self, str_cfg: StructureConfig, content): 14 | """ 15 | Generate RTL design for base control infrastructure. This will generate the sim ctrl wrapper for VIO control. 16 | """ 17 | 18 | # Generate simulation control wrapper and add to target sources 19 | with (open(self._simctrlwrap_path, 'w')) as ctrl_file: 20 | ctrl_file.write(ModuleVIOSimCtrl(scfg=str_cfg, plugin_includes=self.plugin_includes).render()) 21 | 22 | content.verilog_sources += [VerilogSource(files=self._simctrlwrap_path, name='simctrlwrap')] 23 | 24 | def gen_ctrl_infrastructure(self, content): 25 | """ 26 | Generate RTL design for FPGA specific control infrastructure, depending on the interface selected for communication. 27 | For VIO control, no additional RTL sources need to be generated. 28 | 29 | """ 30 | pass 31 | 32 | def add_ip_cores(self, scfg, ip_dir): 33 | """ 34 | Configures and adds IP cores that are necessary for selected IP cores. VIO IP core is configured and added. 35 | :return rendered template for configuring a vio IP core 36 | """ 37 | return [TemplVIO(scfg=scfg, ip_dir=ip_dir)] 38 | 39 | 40 | def main(): 41 | ctrl = VIOControlInfrastructure(prj_cfg=EmuConfig(root='test', cfg_file='')) 42 | ctrl.gen_ctrlwrapper(str_cfg=StructureConfig(prj_cfg=EmuConfig(root='test', cfg_file='')), content='') 43 | 44 | if __name__ == "__main__": 45 | main() -------------------------------------------------------------------------------- /.github/workflows/regression.yml: -------------------------------------------------------------------------------- 1 | name: Regression 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: 0 11 * * ? 8 | 9 | jobs: 10 | linux: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | - name: Set up Python 3.7 16 | uses: actions/setup-python@v2 17 | with: 18 | python-version: 3.7 19 | - name: Install dependencies 20 | run: sudo apt-get install iverilog 21 | - name: Run regression test 22 | run: source regress.sh 23 | env: 24 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 25 | mac: 26 | runs-on: macos-latest 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v2 30 | - name: Set up Python 3.7 31 | uses: actions/setup-python@v2 32 | with: 33 | python-version: 3.7 34 | - name: Install dependencies 35 | run: | 36 | brew install icarus-verilog 37 | - name: Run regression test 38 | run: source regress.sh 39 | env: 40 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 41 | 42 | windows: 43 | runs-on: windows-latest 44 | steps: 45 | - name: Checkout 46 | uses: actions/checkout@v2 47 | - name: Set up Python 3.7 48 | uses: actions/setup-python@v2 49 | with: 50 | python-version: 3.7 51 | - name: Install dependencies 52 | run: | 53 | curl -L https://github.com/sgherbst/anasymod/releases/download/bogus/iverilog-v11-20201123-x64.tar.gz > iverilog-v11-20201123-x64.tar.gz 54 | tar xzvf iverilog-v11-20201123-x64.tar.gz 55 | shell: bash 56 | - name: Run regression test 57 | run: | 58 | export ICARUS_INSTALL_PATH=`realpath iverilog` 59 | echo $ICARUS_INSTALL_PATH 60 | source regress.sh 61 | env: 62 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 63 | shell: bash 64 | - name: Archive debugging artifacts 65 | if: always() 66 | uses: actions/upload-artifact@v2 67 | with: 68 | name: debug-artifacts-windows 69 | path: | 70 | **/models/default/main/*.*v 71 | -------------------------------------------------------------------------------- /anasymod/templates/clk_wiz.py: -------------------------------------------------------------------------------- 1 | from anasymod.templates.generic_ip import TemplGenericIp 2 | from anasymod.targets import FPGATarget 3 | from anasymod.config import EmuConfig 4 | 5 | class TemplClkWiz(TemplGenericIp): 6 | def __init__(self, target: FPGATarget): 7 | # defaults 8 | scfg = target.str_cfg 9 | pcfg = target.prj_cfg 10 | 11 | #################################################### 12 | # Generate ip core config for clk wizard 13 | #################################################### 14 | props = {} 15 | # Add input clks 16 | props['CONFIG.PRIM_IN_FREQ'] = str(pcfg.board.clk_freq * 1e-6) 17 | if len(scfg.clk_i) == 2: 18 | props['CONFIG.PRIM_SOURCE'] = 'Differential_clock_capable_pin' 19 | elif len(scfg.clk_i) == 1: 20 | props['CONFIG.PRIM_SOURCE'] = 'Single_ended_clock_capable_pin' 21 | else: 22 | raise Exception("Wrong number of master clk pins is provided") 23 | 24 | # Add emu_clk_2x 25 | props[f'CONFIG.CLKOUT1_USED'] = 'true' 26 | props['CONFIG.CLKOUT1_REQUESTED_OUT_FREQ'] = (scfg.emu_clk_2x.freq * 1e-6) 27 | 28 | # Add dbg_clk 29 | props[f'CONFIG.CLKOUT2_USED'] = 'true' 30 | props[f'CONFIG.CLKOUT2_REQUESTED_OUT_FREQ'] = (scfg.dbg_clk.freq * 1e-6) 31 | 32 | # Add additional independent clks 33 | for k, clk in enumerate(scfg.clk_independent): 34 | props[f'CONFIG.CLKOUT{k + 3}_USED'] = 'true' 35 | props[f'CONFIG.CLKOUT{k + 3}_REQUESTED_OUT_FREQ'] = (clk.freq * 1e-6) 36 | 37 | #################################################### 38 | # Prepare Template substitutions 39 | #################################################### 40 | 41 | props[f'CONFIG.NUM_OUT_CLKS'] = len(scfg.clk_independent) + 2 42 | 43 | super().__init__(ip_name='clk_wiz', ip_dir=target.ip_dir, props=props) 44 | 45 | def main(): 46 | print(TemplClkWiz(target=FPGATarget(prj_cfg=EmuConfig(root='test', cfg_file=''))).render()) 47 | 48 | if __name__ == "__main__": 49 | main() 50 | -------------------------------------------------------------------------------- /unittests/buck/gen.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | 3 | from argparse import ArgumentParser 4 | 5 | from msdsl import MixedSignalModel, VerilogGenerator, AnalogInput, DigitalInput, AnalogOutput, AnalogSignal, Deriv, eqn_case 6 | from anasymod import json2obj, get_full_path 7 | 8 | def main(): 9 | print('Running model generator...') 10 | 11 | # parse command line arguments 12 | parser = ArgumentParser() 13 | parser.add_argument('-o', '--output', type=str) 14 | parser.add_argument('--dt', type=float) 15 | args = parser.parse_args() 16 | 17 | # load config options 18 | config_file_path = os.path.join(os.path.dirname(get_full_path(__file__)), 'config.json') 19 | cfg = json2obj(open(config_file_path, 'r').read()) 20 | 21 | # create the model 22 | model = MixedSignalModel('buck', DigitalInput('hs'), DigitalInput('ls'), AnalogInput('v_in'), AnalogOutput('v_out'), 23 | AnalogOutput('i_ind'), dt=args.dt) 24 | 25 | # internal state variable 26 | model.add_analog_state('v_snub', 1000) 27 | 28 | # dynamics 29 | i_snub = AnalogSignal('i_snub') 30 | v_sw = AnalogSignal('v_sw') 31 | 32 | cond_hs = eqn_case([0, 1/cfg.r_sw], [model.hs]) 33 | cond_ls = eqn_case([0, 1/cfg.r_sw], [model.ls]) 34 | 35 | model.add_eqn_sys([ 36 | # Current into snubber capacitor 37 | i_snub == (v_sw - model.v_snub) / cfg.r_snub, 38 | 39 | # KCL at switch node 40 | (cond_hs*(model.v_in - v_sw)) == cond_ls*v_sw + i_snub + model.i_ind, 41 | 42 | # Inductor behavior 43 | Deriv(model.i_ind) == (v_sw - model.v_out)/cfg.ind, 44 | 45 | # Capacitors 46 | Deriv(model.v_snub) == i_snub/cfg.c_snub, 47 | Deriv(model.v_out) == (model.i_ind-model.v_out/cfg.r_load)/cfg.c_load 48 | ]) 49 | 50 | # add probes 51 | #model.add_probe(model.v_snub) 52 | 53 | # determine the output filename 54 | filename = os.path.join(get_full_path(args.output), f'{model.module_name}.sv') 55 | print('Model will be written to: ' + filename) 56 | 57 | # generate the model 58 | model.compile_to_file(VerilogGenerator(), filename) 59 | 60 | if __name__ == '__main__': 61 | main() -------------------------------------------------------------------------------- /unittests/one_clock/sim_ctrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module sim_ctrl ( 4 | input clk_i, 5 | output reg [31:0] t_lo, 6 | output reg [31:0] t_hi 7 | ); 8 | `include "anasymod.sv" 9 | 10 | // set t_lo and t_hi 11 | parameter real t_lo_val = 0.123e-12; 12 | parameter real t_hi_val = 0.234e-12; 13 | initial begin 14 | t_lo = t_lo_val/(`DT_SCALE); 15 | t_hi = t_hi_val/(`DT_SCALE); 16 | end 17 | 18 | // checking of the low and high periods 19 | integer i; 20 | real t_last_rise, t_rise; 21 | real t_last_fall, t_fall; 22 | real t_dur_lo, t_dur_hi; 23 | 24 | function integer isclose ( 25 | input real meas, 26 | input real expct, 27 | input real abstol 28 | ); 29 | isclose = ((expct-abstol)<=meas) && (meas<=(expct+abstol)); 30 | endfunction 31 | 32 | initial begin 33 | wait_emu_reset(); 34 | 35 | // get the time of the first rising edge 36 | @(posedge clk_i); 37 | #(1e-9*1s); 38 | t_last_rise = get_emu_time(); 39 | 40 | // get the time of the first falling edge 41 | @(negedge clk_i); 42 | #(1e-9*1s); 43 | t_last_fall = get_emu_time(); 44 | 45 | // check several periods 46 | for (i=0; i<10; i=i+1) begin 47 | // check the low duration 48 | @(posedge clk_i); 49 | #(1e-9*1s); 50 | t_rise = get_emu_time(); 51 | t_dur_lo = t_rise - t_last_fall; 52 | if (!isclose(t_dur_lo, t_lo_val, 1e-15)) begin 53 | $error("%0d(a) Low duration out of spec: %0e", i, t_dur_lo); 54 | end else begin 55 | $display("%0d(a) Low duration in spec: %0e", i, t_dur_lo); 56 | end 57 | t_last_rise = t_rise; 58 | 59 | // check the high duration 60 | @(negedge clk_i); 61 | #(1e-9*1s); 62 | t_fall = get_emu_time(); 63 | t_dur_hi = t_fall - t_last_rise; 64 | if (!isclose(t_dur_hi, t_hi_val, 1e-15)) begin 65 | $error("%0d(b) High duration out of spec: %0e", i, t_dur_hi); 66 | end else begin 67 | $display("%0d(b) High duration in spec: %0e", i, t_dur_hi); 68 | end 69 | t_last_fall = t_fall; 70 | end 71 | 72 | // finish the simulation 73 | $finish; 74 | end 75 | endmodule -------------------------------------------------------------------------------- /anasymod/sim/icarus.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | 4 | from anasymod.sim.sim import Simulator 5 | from anasymod.util import call 6 | 7 | class IcarusSimulator(Simulator): 8 | def compile(self): 9 | # build up the simulation command 10 | cmd = [self.cfg.icarus_config.iverilog, '-g2012', '-o', self.cfg.icarus_config.output_file_path, '-s', 11 | self.target.cfg.top_module] 12 | 13 | # if desired, only preprocess 14 | if self.cfg.cfg.preprocess_only: 15 | cmd.append('-E') 16 | 17 | # add defines 18 | for define in self.target.content.defines: 19 | for k, v in define.define.items(): 20 | if v is not None: 21 | cmd.extend(['-D', f"{k}={v}"]) 22 | else: 23 | cmd.extend(['-D', f"{k}"]) 24 | 25 | # add include directories, remove filename from paths and create a list of inc dirs removing duplicates 26 | inc_dirs = set() 27 | 28 | for sources in self.target.content.verilog_headers: 29 | for src in sources.files: 30 | inc_dirs.add(os.path.dirname(src)) 31 | 32 | for sources in self.target.content.include_dirs: 33 | for src in sources.files: 34 | inc_dirs.add(src) 35 | 36 | for inc_dir in inc_dirs: 37 | cmd.extend(['-I', inc_dir]) 38 | 39 | # add verilog source files 40 | for sources in self.target.content.verilog_sources: 41 | for src in sources.files: 42 | cmd.append(src) 43 | 44 | # add HDL files for functional models 45 | for sources in self.target.content.functional_models: 46 | for src in sources.gen_files: 47 | cmd.append(src) 48 | 49 | # add any additional user-supplied flags 50 | for flag in self.flags: 51 | cmd.append(str(flag)) 52 | 53 | # run iverilog 54 | call(cmd, cwd=self.cfg.build_root) 55 | 56 | def run(self): 57 | args = [self.cfg.icarus_config.vvp, self.cfg.icarus_config.output_file_path] 58 | cwd = self.cfg.build_root 59 | err_str = re.compile('^(ERROR|FATAL):') 60 | call(args, cwd=cwd, err_str=err_str) 61 | 62 | def simulate(self): 63 | self.compile() 64 | 65 | if not self.cfg.cfg.preprocess_only: 66 | self.run() 67 | -------------------------------------------------------------------------------- /unittests/multi_clock/osc_checker.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module osc_checker #( 4 | parameter integer index=0, 5 | parameter integer num_periods = 10, 6 | parameter real precision = 1e-15 7 | ) ( 8 | input clk_i, 9 | input real t_lo_val, 10 | input real t_hi_val, 11 | output reg done 12 | ); 13 | // include anasymod control functions 14 | `include "anasymod.sv" 15 | 16 | // variable declaration 17 | integer i; 18 | real t_last_rise, t_rise; 19 | real t_last_fall, t_fall; 20 | real t_dur_lo, t_dur_hi; 21 | 22 | // convenience function 23 | function integer isclose ( 24 | input real meas, 25 | input real expct, 26 | input real abstol 27 | ); 28 | isclose = ((expct-abstol)<=meas) && (meas<=(expct+abstol)); 29 | endfunction 30 | 31 | // main logic 32 | initial begin 33 | done = 1'b0; 34 | wait_emu_reset(); 35 | 36 | // get the time of the first rising edge 37 | @(posedge clk_i); 38 | #(1e-9*1s); 39 | t_last_rise = get_emu_time(); 40 | 41 | // get the time of the first falling edge 42 | @(negedge clk_i); 43 | #(1e-9*1s); 44 | t_last_fall = get_emu_time(); 45 | 46 | // check several periods 47 | for (i=0; i 3 | #include 4 | #include "sleep.h" 5 | 6 | #define SET_A 1 7 | #define SET_B 2 8 | #define SET_MODE 3 9 | #define GET_C 4 10 | 11 | #define BUF_SIZE 32 12 | 13 | int main() { 14 | // character buffering 15 | u32 idx = 0; 16 | char rcv; 17 | char buf [BUF_SIZE]; 18 | 19 | // command processing; 20 | u32 cmd; 21 | u32 arg1; 22 | u32 nargs = 0; 23 | 24 | if (init_GPIO() != 0) { 25 | xil_printf("GPIO Initialization Failed\r\n"); 26 | return XST_FAILURE; 27 | } 28 | 29 | while (1) { 30 | rcv = inbyte(); 31 | if ((rcv == ' ') || (rcv == '\t') || (rcv == '\r') || (rcv == '\n')) { 32 | // whitespace 33 | if (idx > 0) { 34 | // pad rest of the string with null characters 35 | // this appears to be necessary to prevent 36 | // memory corruption 37 | for (; idx= emu_time_s) ? 47 | (((emu_ctrl_data - emu_time_s) <= emu_dt_max) ? 48 | (emu_ctrl_data - emu_time_s) : 49 | emu_dt_max 50 | ) : 51 | 0 52 | ); 53 | //begin 54 | //if (emu_ctrl_data >= emu_time) begin 55 | // emu_dt_req = (emu_ctrl_data - emu_time_s); 56 | //end else begin 57 | // emu_dt_req = '0; 58 | //end 59 | //end 60 | 61 | 62 | 2'b11: emu_dt_req = (emu_ctrl_data <= emu_dt_max) ? emu_ctrl_data : emu_dt_max; 63 | default: emu_dt_req = '1; 64 | endcase 65 | end 66 | 67 | assign dt_req_stall = emu_dt_req ; 68 | endmodule -------------------------------------------------------------------------------- /anasymod/structures/firmware_gpio.py: -------------------------------------------------------------------------------- 1 | class FirmwareGPIO: 2 | def __init__(self, scfg): 3 | crtl_inputs = scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs 4 | ctrl_outputs = scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs 5 | 6 | self.getter_dict = {} 7 | for probe in ctrl_outputs: 8 | if probe.o_addr is not None: 9 | self.getter_dict[probe.o_addr] = probe.name 10 | 11 | self.setter_dict = {} 12 | for param in crtl_inputs: 13 | if param.i_addr is not None: 14 | self.setter_dict[param.i_addr] = param.name 15 | 16 | self.hdr_text = self.gen_hdr_text() 17 | self.src_text = self.gen_src_text() 18 | 19 | def gen_hdr_text(self): 20 | retval = ''' 21 | #include "xgpio.h" 22 | 23 | int init_GPIO(); 24 | ''' 25 | 26 | # add setter declarations 27 | for k, v in self.setter_dict.items(): 28 | retval += f''' 29 | void set_{v}(u32 val); 30 | ''' 31 | 32 | # add getter declarations 33 | for k, v in self.getter_dict.items(): 34 | retval += f''' 35 | u32 get_{v}(); 36 | ''' 37 | 38 | # return the code 39 | return retval 40 | 41 | def gen_src_text(self): 42 | retval = ''' 43 | #include "xparameters.h" 44 | #include "xgpio.h" 45 | #include "sleep.h" 46 | 47 | XGpio Gpio0; // chan 1: o_ctrl, chan 2: o_data 48 | XGpio Gpio1; // chan 1: i_ctrl, chan 2: i_data 49 | 50 | int init_GPIO(){ 51 | int status0, status1; 52 | status0 = XGpio_Initialize(&Gpio0, XPAR_GPIO_0_DEVICE_ID); 53 | status1 = XGpio_Initialize(&Gpio1, XPAR_GPIO_1_DEVICE_ID); 54 | if ((status0 == XST_SUCCESS) && (status1 == XST_SUCCESS)) { 55 | return 0; 56 | } else { 57 | return 1; 58 | } 59 | } 60 | 61 | u32 get_value(u32 addr){ 62 | XGpio_DiscreteWrite(&Gpio0, 1, addr); 63 | usleep(1); 64 | return XGpio_DiscreteRead(&Gpio0, 2); 65 | } 66 | 67 | void set_value(u32 addr, u32 val){ 68 | // set address and data 69 | XGpio_DiscreteWrite(&Gpio1, 1, addr); 70 | XGpio_DiscreteWrite(&Gpio1, 2, val); 71 | usleep(1); 72 | 73 | // assert "valid" 74 | XGpio_DiscreteWrite(&Gpio1, 1, addr | (1UL << 30)); 75 | usleep(1); 76 | 77 | // de-assert "valid" 78 | XGpio_DiscreteWrite(&Gpio1, 1, addr); 79 | usleep(1); 80 | } 81 | ''' 82 | 83 | # add setter definitions 84 | for k, v in self.setter_dict.items(): 85 | retval += f''' 86 | void set_{v}(u32 val){{ 87 | set_value({k}, val); 88 | }} 89 | ''' 90 | 91 | # add setter definitions 92 | for k, v in self.getter_dict.items(): 93 | retval += f''' 94 | u32 get_{v}(){{ 95 | return get_value({k}); 96 | }} 97 | ''' 98 | # return the code 99 | return retval -------------------------------------------------------------------------------- /anasymod/templates/xsct_build.py: -------------------------------------------------------------------------------- 1 | class TemplXSCTBuild: 2 | def __init__(self, sdk_path, version_year, version_number, 3 | proc_name='ps7_cortexa9_0', os_name='standalone', 4 | hw_name='hw', hw_path=None, sw_name='sw', 5 | template_name='Empty Application', create=True, 6 | build=True): 7 | 8 | # save version information 9 | self.version_year = version_year 10 | self.version_number = version_number 11 | 12 | # initialize text 13 | self.text = '' 14 | 15 | # apply commands 16 | 17 | self.setws(sdk_path=sdk_path) 18 | 19 | if create: 20 | self.app_create( 21 | hw_name=hw_name, 22 | hw_path=hw_path, 23 | sw_name=sw_name, 24 | proc_name=proc_name, 25 | template_name=template_name, 26 | os_name=os_name 27 | ) 28 | 29 | if build: 30 | self.app_build( 31 | sw_name=sw_name 32 | ) 33 | 34 | def line(self, s='', nl='\n'): 35 | self.text += f'{s}{nl}' 36 | 37 | def comment(self, s): 38 | self.line(f'# {s}') 39 | 40 | def setws(self, sdk_path): 41 | self.comment('set the work directory') 42 | self.line(f'setws "{sdk_path.as_posix()}"') 43 | self.line() 44 | 45 | def app_create(self, hw_name, hw_path, sw_name, proc_name, 46 | template_name, os_name): 47 | if self.version_year < 2020: 48 | hw_path_hdf = hw_path.with_suffix('.hdf') 49 | self.comment('create the hardware configuration') 50 | self.line(f'file copy -force "{hw_path.as_posix()}" "{hw_path_hdf.as_posix()}"') 51 | self.line(f'createhw -name {hw_name} -hwspec "{hw_path_hdf.as_posix()}"') 52 | #self.line(f'createhw -name {hw_name} -hwspec "C:/Inicio_dev/fpga_flow/anasymod/tests/firmware/build/fpga/prj/prj.sdk/top.hdf"') 53 | self.line() 54 | self.comment('create the software configuration') 55 | self.line(f'createapp -name {sw_name} -hwproject {hw_name} ' 56 | f'-proc {proc_name} -app "{template_name}"') 57 | self.line() 58 | else: 59 | self.comment('create the app configuration') 60 | self.line(f'app create -name {sw_name} -hw "{hw_path.as_posix()}" -os {os_name}' 61 | f' -proc {proc_name} -template "{template_name}"') 62 | self.line() 63 | 64 | def app_build(self, sw_name): 65 | self.comment('build application') 66 | if self.version_year < 2020: 67 | self.line('projects -build') 68 | else: 69 | self.line(f'app build -name {sw_name}') 70 | self.line() -------------------------------------------------------------------------------- /anasymod/structures/module_traceport.py: -------------------------------------------------------------------------------- 1 | from anasymod.templates.templ import JinjaTempl 2 | from anasymod.config import EmuConfig 3 | from anasymod.generators.gen_api import SVAPI, ModuleInst 4 | from anasymod.structures.structure_config import StructureConfig 5 | from anasymod.sim_ctrl.datatypes import DigitalSignal 6 | 7 | class ModuleTracePort(JinjaTempl): 8 | def __init__(self, scfg: StructureConfig): 9 | super().__init__(trim_blocks=True, lstrip_blocks=True) 10 | probes = scfg.digital_probes + scfg.analog_probes + [scfg.time_probe] + [scfg.dec_cmp] 11 | 12 | ##################################################### 13 | # Define module ios 14 | ##################################################### 15 | 16 | self.module_ifc = SVAPI() 17 | module = ModuleInst(api=self.module_ifc, name="trace_port_gen") 18 | # Add probe signals 19 | module.add_inputs(probes) 20 | 21 | # Add master clk 22 | module.add_input(scfg.emu_clk) 23 | 24 | module.generate_header() 25 | 26 | ##################################################### 27 | # CPU sim control section - add dump statements 28 | ##################################################### 29 | 30 | self.probe_dumps = SVAPI() 31 | self.probe_dumps.indent() 32 | self.probe_dumps.writeln(f'initial begin') 33 | self.probe_dumps.indent() 34 | self.probe_dumps.writeln('#0;') 35 | for probe in probes: 36 | self.probe_dumps.writeln(f'$dumpvars(0, {probe.name});') 37 | self.probe_dumps.dedent() 38 | self.probe_dumps.writeln(f'end') 39 | 40 | ##################################################### 41 | # FPGA sim control section - Instantiate ila core 42 | ##################################################### 43 | 44 | # Instantiate ila core 45 | self.ila_wiz_inst = SVAPI() 46 | ila_wiz = ModuleInst(api=self.ila_wiz_inst, name="ila_0") 47 | for k, signal in enumerate(probes): # Add probe signals 48 | ila_wiz.add_input(DigitalSignal(name=f'probe{k}', abspath=None, width=signal.width), connection=signal) 49 | ila_wiz.add_input(DigitalSignal(name='clk', abspath=None, width=1), connection=scfg.emu_clk) # Add master clk 50 | ila_wiz.generate_instantiation() 51 | 52 | 53 | TEMPLATE_TEXT = ''' 54 | `timescale 1ns/1ps 55 | 56 | `default_nettype none 57 | {{subst.module_ifc.text}} 58 | 59 | `ifdef SIMULATION_MODE_MSDSL 60 | {{subst.probe_dumps.text}} 61 | `else 62 | // ILA instantiation 63 | {{subst.ila_wiz_inst.text}} 64 | 65 | `endif // `ifdef SIMULATION_MODE_MSDSL 66 | 67 | endmodule 68 | `default_nettype wire 69 | ''' 70 | 71 | def main(): 72 | print(ModuleTracePort(scfg=StructureConfig(prj_cfg=EmuConfig(root='test', cfg_file=''))).render()) 73 | 74 | if __name__ == "__main__": 75 | main() -------------------------------------------------------------------------------- /anasymod/templates/probe_extract.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from anasymod.templates.templ import JinjaTempl 4 | from anasymod.config import EmuConfig 5 | from anasymod.util import back2fwd 6 | from anasymod.targets import FPGATarget 7 | 8 | class TemplPROBE_EXTRACT(JinjaTempl): 9 | def __init__(self, target: FPGATarget): 10 | super().__init__() 11 | self.project_dir = back2fwd(target.project_root) 12 | self.dcp_path = back2fwd(os.path.join(self.project_dir, target.prj_cfg.vivado_config.project_name + r".runs", r"synth_1", target.cfg.top_module + r".dcp")) 13 | 14 | TEMPLATE_TEXT = ''' 15 | # Load synthesized design 16 | open_checkpoint "{{subst.dcp_path}}" 17 | 18 | # Extract analog_signals 19 | set ana_s [get_nets -hier -filter {analog_signal == "true"}] 20 | 21 | regsub -all "\[{1}[0123456789]+\]{1}" $ana_s "" ana_s 22 | set ana_s [lsort -unique $ana_s] 23 | 24 | set ana_s_exponents [list] 25 | set ana_s_widths [list] 26 | 27 | foreach {signal} $ana_s { 28 | append signal [0] 29 | lappend ana_s_exponents [get_property fixed_point_exponent [get_nets $signal]] 30 | lappend ana_s_widths [get_property BUS_WIDTH [get_nets $signal]] 31 | } 32 | 33 | # Extract time_signal 34 | set time_s [get_nets -hier -filter {time_signal == "true"}] 35 | regsub -all "\[{1}[0123456789]+\]{1}" $time_s "" time_s 36 | set time_s [lsort -unique $time_s] 37 | set time_s_tmp $time_s 38 | append time_s_tmp [0] 39 | 40 | set time_s_exponent [get_property fixed_point_exponent [get_nets $time_s_tmp]] 41 | set time_s_width [get_property BUS_WIDTH [get_nets $time_s_tmp]] 42 | 43 | # Extract reset_signal 44 | set reset_s [get_nets -hier -filter {reset_signal == "true"}] 45 | 46 | # Extract other_signals marked for debug 47 | set other_s [get_nets -hier -filter {digital_signal == "true" && MARK_DEBUG}] 48 | 49 | set sb_s [list] 50 | set sb_s [lsearch -regexp -not -inline -all $other_s "\[{1}[0123456789]+\]{1}"] 51 | 52 | set mb_s [list] 53 | set mb_s [lsearch -regexp -inline -all $other_s "\[{1}[0123456789]+\]{1}"] 54 | regsub -all "\[{1}[0123456789]+\]{1}" $mb_s "" mb_s 55 | set mb_s [lsort -unique $mb_s] 56 | 57 | set mb_s_widths [list] 58 | 59 | foreach {signal} $mb_s { 60 | append signal [0] 61 | lappend mb_s_widths [get_property BUS_WIDTH [get_nets $signal]] 62 | } 63 | 64 | set outputFile [open "{{subst.project_dir}}/probe_config.txt" w] 65 | puts $outputFile [concat "ANALOG:" $ana_s] 66 | puts $outputFile [concat "ANALOG_EXPONENT:" $ana_s_exponents] 67 | puts $outputFile [concat "ANALOG_WIDTH:" $ana_s_widths] 68 | puts $outputFile [concat "TIME:" $time_s] 69 | puts $outputFile [concat "TIME_EXPONENT:" $time_s_exponent] 70 | puts $outputFile [concat "TIME_WIDTH:" $time_s_width] 71 | puts $outputFile [concat "RESET:" $reset_s] 72 | puts $outputFile [concat "SB:" $sb_s] 73 | puts $outputFile [concat "MB:" $mb_s] 74 | puts $outputFile [concat "MB_WIDTH:" $mb_s_widths] 75 | close $outputFile 76 | 77 | close_design 78 | ''' 79 | 80 | def main(): 81 | print(TemplPROBE_EXTRACT(cfg=EmuConfig()).render()) 82 | 83 | if __name__ == "__main__": 84 | main() -------------------------------------------------------------------------------- /anasymod/templates/launch_ILA_tcl.py: -------------------------------------------------------------------------------- 1 | from anasymod.templates.templ import JinjaTempl 2 | from anasymod.util import back2fwd 3 | from anasymod.generators.gen_api import SVAPI 4 | from anasymod.config import EmuConfig 5 | from anasymod.structures.structure_config import StructureConfig 6 | 7 | class TemplLAUNCH_ILA_TCL(JinjaTempl): 8 | def __init__(self, pcfg: EmuConfig, scfg: StructureConfig, ltxfile_path, server_addr: str): 9 | super().__init__(trim_blocks=False, lstrip_blocks=False) 10 | pcfg = pcfg 11 | scfg = scfg 12 | 13 | # set server address 14 | self.server_addr = server_addr 15 | 16 | # set the paths to the LTX file 17 | self.ltx_file = back2fwd(ltxfile_path) 18 | 19 | # set the JTAG frequency. sometimes it is useful to try a slower frequency than default if there 20 | # are problems with the debug hub clock 21 | self.jtag_freq = str(int(pcfg.cfg.jtag_freq)) 22 | 23 | # set the "short" device name which is used to distinguish the FPGA part from other USB devices 24 | self.device_name = pcfg.board.short_part_name 25 | 26 | # Set aliases for probes 27 | self.probe_aliases = SVAPI() 28 | for probe in scfg.digital_probes + scfg.analog_probes + [scfg.time_probe]: 29 | self.probe_aliases.writeln(f'set {probe.name} [get_hw_probes "trace_port_gen_i/{probe.name}" -of_objects $ila_0_i]') 30 | 31 | # Set radix for probes 32 | self.probe_radix = SVAPI() 33 | for digital_probe in (scfg.digital_probes + [scfg.time_probe]): 34 | signed = 'SIGNED' if digital_probe.signed else 'UNSIGNED' 35 | self.probe_radix.writeln(f'set_property DISPLAY_RADIX {signed} ${digital_probe.name}') 36 | 37 | for analog_probe in scfg.analog_probes: 38 | self.probe_radix.writeln(f'set_property DISPLAY_RADIX SIGNED ${analog_probe.name}') 39 | 40 | TEMPLATE_TEXT = '''\ 41 | # Connect to hardware 42 | open_hw 43 | catch {disconnect_hw_server} 44 | {% if subst.server_addr is none %} 45 | connect_hw_server 46 | {% else %} 47 | connect_hw_server -url {{subst.server_addr}} 48 | {% endif %} 49 | set_property PARAM.FREQUENCY {{subst.jtag_freq}} [get_hw_targets] 50 | open_hw_target 51 | 52 | # Configure files to be programmed 53 | set my_hw_device [get_hw_devices {{subst.device_name}}*] 54 | current_hw_device $my_hw_device 55 | refresh_hw_device $my_hw_device 56 | set_property PROBES.FILE "{{subst.ltx_file}}" $my_hw_device 57 | set_property FULL_PROBES.FILE "{{subst.ltx_file}}" $my_hw_device 58 | 59 | refresh_hw_device $my_hw_device 60 | 61 | # ILA setup 62 | set ila_0_i [get_hw_ilas -of_objects $my_hw_device -filter {CELL_NAME=~"trace_port_gen_i/ila_0_i"}] 63 | 64 | ############################################## 65 | # Code related to interactive mode starts here 66 | ############################################## 67 | 68 | # configure the ILA for low latency 69 | set_property CORE_REFRESH_RATE_MS 0 $ila_0_i 70 | 71 | # set aliases to ILA probes 72 | {{subst.probe_aliases.text}} 73 | 74 | # configure radix for ILA probes 75 | {{subst.probe_radix.text}} 76 | ''' 77 | 78 | def main(): 79 | print(TemplLAUNCH_ILA_TCL(target=FPGATarget(prj_cfg=EmuConfig(root='', cfg_file=''), plugins=[], name=r"test"), server_addr='').render()) 80 | 81 | if __name__ == "__main__": 82 | main() 83 | -------------------------------------------------------------------------------- /unittests/waveform.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.interpolate 3 | 4 | class Waveform: 5 | def __init__(self, data, time): 6 | self.data = np.array(data, dtype=float) 7 | self.time = np.array(time, dtype=float) 8 | self.interp = scipy.interpolate.interp1d( 9 | time, data, 10 | bounds_error=False, fill_value=(data[0], data[-1]) 11 | ) 12 | 13 | # attach measurement objects in a way that is compatible with pverify 14 | measurements = Measurements(self) 15 | self.Measurements_Base = measurements 16 | self.Measurements_NonPeriodic = measurements 17 | self.Measurements_Periodic = measurements 18 | 19 | def check_in_limits(self, wave_lo, wave_hi): 20 | # compute bounds 21 | lo_bnds = wave_lo.interp(self.time) 22 | hi_bnds = wave_hi.interp(self.time) 23 | 24 | # uncomment for graphical debugging 25 | # import matplotlib.pyplot as plt 26 | # plt.plot(self.time, lo_bnds) 27 | # plt.plot(self.time, hi_bnds) 28 | # plt.plot(self.time, self.data) 29 | # plt.legend(['lo_bnds', 'hi_bnds', 'data']) 30 | # plt.show() 31 | 32 | # find any point where the waveform is out of spec 33 | in_spec = np.logical_and(lo_bnds <= self.data, self.data <= hi_bnds) 34 | if np.all(in_spec): 35 | pass 36 | else: 37 | indices = np.where(np.logical_not(in_spec)) 38 | times = self.time[indices] 39 | raise Exception(f'Waveform is out of spec. Check times: {times}') 40 | 41 | class Measurements: 42 | def __init__(self, wave: Waveform): 43 | self.wave = wave 44 | 45 | def min(self): 46 | return np.min(self.wave.data) 47 | 48 | def max(self): 49 | return np.max(self.wave.data) 50 | 51 | def peak_to_peak(self): 52 | return self.max() - self.min() 53 | 54 | def find_settled(self, lo, hi): 55 | # find first index where the waveform is in the settled range 56 | idx = np.argmax((lo <= self.wave.data) & (self.wave.data <= hi)) 57 | 58 | # if there is no such value, idx will be zero, so we have to check 59 | # for that condition 60 | if not (lo <= self.wave.data[idx] <= hi): 61 | raise Exception('Waveform did not settle to the specified range.') 62 | 63 | return self.wave.time[idx] 64 | 65 | def frequency(self, level=0, slope='rise', hysteresis=0): 66 | # find the crossing times 67 | crossings = [] 68 | armed = False 69 | for t, v in zip(self.wave.time, self.wave.data): 70 | if slope == 'rise': 71 | if armed and (v > (level + hysteresis)): 72 | crossings.append(t) 73 | armed = False 74 | elif v < (level - hysteresis): 75 | armed = True 76 | elif slope == 'fall': 77 | if armed and (v < (level - hysteresis)): 78 | crossings.append(t) 79 | armed = False 80 | elif v > (level + hysteresis): 81 | armed = True 82 | else: 83 | raise Exception(f"Unknown slope type: {slope}") 84 | 85 | # measure time from the first crossing to the last crossing, 86 | # as well as the number of periods 87 | dt = crossings[-1] - crossings[0] 88 | num = len(crossings) - 1 89 | 90 | # return the average frequency 91 | return num/dt 92 | 93 | def frequency_average(self, *args, **kwargs): 94 | # not sure what this function is supposed to do as compared to the previous 95 | # one, so I'm leaving this as an alias to "frequency" for now 96 | return self.frequency(*args, **kwargs) 97 | -------------------------------------------------------------------------------- /anasymod/structures/module_clk_manager.py: -------------------------------------------------------------------------------- 1 | from anasymod.templates.templ import JinjaTempl 2 | from anasymod.config import EmuConfig 3 | from anasymod.generators.gen_api import SVAPI, ModuleInst 4 | from anasymod.structures.structure_config import StructureConfig 5 | from anasymod.sim_ctrl.datatypes import DigitalSignal 6 | 7 | 8 | class ModuleClkManager(JinjaTempl): 9 | """ 10 | This is the generator for clk_gen.sv wrapper. 11 | """ 12 | def __init__(self, scfg: StructureConfig): 13 | super().__init__(trim_blocks=True, lstrip_blocks=True) 14 | 15 | ##################################################### 16 | # Create module interface 17 | ##################################################### 18 | self.module_ifc = SVAPI() 19 | 20 | module = ModuleInst(api=self.module_ifc, name="clk_gen") 21 | module.add_inputs(scfg.clk_i) 22 | module.add_output(scfg.dbg_clk) 23 | module.add_output(scfg.emu_clk_2x) 24 | module.add_outputs(scfg.clk_independent) 25 | module.generate_header() 26 | 27 | ##################################################### 28 | # Instantiate clk wizard 29 | ##################################################### 30 | self.clk_wiz_inst = SVAPI() 31 | 32 | clk_wiz = ModuleInst(api=self.clk_wiz_inst, name='clk_wiz_0') 33 | clk_wiz.add_inputs(scfg.clk_i, connections=scfg.clk_i) 34 | 35 | # handled by emu clk generator 36 | for k, port in enumerate([scfg.emu_clk_2x] + [scfg.dbg_clk] + scfg.clk_independent): 37 | clk_wiz.add_output(DigitalSignal(abspath=None, width=1, name=f'clk_out{k + 1}'), connection=port) 38 | 39 | clk_wiz.add_input(DigitalSignal(abspath=None, width=1, name='reset'), connection=r"1'b0") 40 | clk_wiz.add_output(DigitalSignal(abspath=None, width=1, name='locked'), DigitalSignal(abspath=None, width=1, name='locked')) 41 | 42 | clk_wiz.generate_instantiation() 43 | 44 | ##################################################### 45 | # Create independent clks for simulation case 46 | ##################################################### 47 | 48 | self.emu_clk = scfg.emu_clk 49 | self.independent_clks = scfg.clk_independent 50 | 51 | TEMPLATE_TEXT = '''\ 52 | `timescale 1ns/1ps 53 | 54 | `default_nettype none 55 | {{subst.module_ifc.text}} 56 | 57 | `ifdef SIMULATION_MODE_MSDSL 58 | // emulator clock sequence 59 | logic emu_clk_2x_state; 60 | {% for clk in subst.independent_clks %} 61 | logic {{clk.name}}_state; 62 | {% endfor %} 63 | 64 | initial begin 65 | // since the reset signal is initially "1", this delay+posedge will 66 | // cause the MSDSL templates to be reset 67 | emu_clk_2x_state = 1'b0; 68 | #((0.25/(`EMU_CLK_FREQ))*1s); 69 | emu_clk_2x_state = 1'b1; 70 | 71 | // clock runs forever 72 | forever begin 73 | #((0.25/(`EMU_CLK_FREQ))*1s); 74 | emu_clk_2x_state = ~emu_clk_2x_state; 75 | end 76 | end 77 | 78 | {% for clk in subst.independent_clks %} 79 | initial begin 80 | {{clk.name}}_state = 1'b0; 81 | forever begin 82 | #(({{0.5/clk.freq}})*1s); 83 | {{clk.name}}_state = ~{{clk.name}}_state; 84 | end 85 | end 86 | {% endfor %} 87 | 88 | // output assignment 89 | assign emu_clk_2x = emu_clk_2x_state; 90 | {% for clk in subst.independent_clks %} 91 | assign {{clk.name}} = {{clk.name}}_state; 92 | {% endfor %} 93 | `else 94 | logic locked; 95 | {{subst.clk_wiz_inst.text}} 96 | `endif // `ifdef SIMULATION_MODE_MSDSL 97 | 98 | endmodule 99 | `default_nettype wire 100 | ''' 101 | 102 | def main(): 103 | print(ModuleClkManager(scfg=StructureConfig(prj_cfg=EmuConfig(root='test', cfg_file=''))).render()) 104 | 105 | if __name__ == "__main__": 106 | main() -------------------------------------------------------------------------------- /anasymod/structures/uart_zynq_firmware_appcode.py: -------------------------------------------------------------------------------- 1 | class UartZynqFirmwareAppCode: 2 | def __init__(self, scfg): 3 | crtl_inputs = scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs 4 | ctrl_outputs = scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs 5 | 6 | self.getter_dict = {} 7 | for probe in ctrl_outputs: 8 | if probe.o_addr is not None: 9 | self.getter_dict[probe.o_addr] = probe.name 10 | 11 | self.setter_dict = {} 12 | for param in crtl_inputs: 13 | if param.i_addr is not None: 14 | self.setter_dict[param.i_addr] = param.name 15 | 16 | self.src_text = self.gen_src_text() 17 | 18 | def gen_src_text(self): 19 | retval = ''' 20 | #include "gpio_funcs.h" 21 | #include 22 | #include 23 | #include "sleep.h" 24 | ''' 25 | 26 | idx = 0 27 | 28 | # add setter defines 29 | for k, v in self.setter_dict.items(): 30 | retval += f''' 31 | #define SET_{v} {idx}''' 32 | idx += 1 33 | 34 | # add getter defines 35 | for k, v in self.getter_dict.items(): 36 | retval += f''' 37 | #define GET_{v} {idx}''' 38 | idx += 1 39 | 40 | # add default body 1 41 | retval += r''' 42 | 43 | int main() { 44 | // character buffering 45 | u32 idx = 0; 46 | char rcv; 47 | char buf [32]; 48 | 49 | // command processing; 50 | u32 cmd; 51 | u32 arg1; 52 | u32 nargs = 0; 53 | 54 | if (init_GPIO() != 0) { 55 | xil_printf("GPIO Initialization Failed\r\n"); 56 | return XST_FAILURE; 57 | } 58 | 59 | while (1) { 60 | rcv = inbyte(); 61 | if ((rcv == ' ') || (rcv == '\t') || (rcv == '\r') || (rcv == '\n')) { 62 | // whitespace 63 | if (idx > 0) { 64 | buf[idx++] = '\0'; 65 | if (nargs == 0) { 66 | if (strcmp(buf, "HELLO") == 0) { 67 | xil_printf("Hello World!\r\n"); 68 | nargs = 0; 69 | } else if (strcmp(buf, "EXIT") == 0) { 70 | return 0; 71 | ''' 72 | 73 | #add cmd interpreter for setters 74 | for k, v in self.setter_dict.items(): 75 | retval += f''' 76 | }} else if (strcmp(buf, "SET_{v}") == 0) {{ 77 | cmd = SET_{v}; 78 | nargs++; 79 | ''' 80 | 81 | # add cmd interpreter for getters 82 | for k, v in self.getter_dict.items(): 83 | retval += f''' 84 | }} else if (strcmp(buf, "GET_{v}") == 0) {{ 85 | xil_printf("%0d\\r\\n", get_{v}()); 86 | nargs = 0; 87 | ''' 88 | 89 | # add default body 2 90 | retval += r''' 91 | } else { 92 | xil_printf("ERROR: Unknown command\r\n"); 93 | } 94 | } else if (nargs == 1) { 95 | sscanf(buf, "%lu", &arg1); 96 | ''' 97 | 98 | # add setter argument reader 99 | cond_str = 'if' 100 | for k, v in self.setter_dict.items(): 101 | retval += f''' 102 | {cond_str} (cmd == SET_{v}) {{ 103 | set_{v}(arg1)\n; 104 | ''' + \ 105 | r''' 106 | xil_printf("0\r\n"); 107 | ''' 108 | cond_str = '} else if' 109 | 110 | # add default body 3 111 | retval += ''' 112 | } 113 | nargs = 0; 114 | } 115 | } 116 | idx = 0; 117 | } else { 118 | // load next character 119 | buf[idx++] = rcv; 120 | } 121 | } 122 | 123 | return 0; 124 | } 125 | ''' 126 | 127 | # return the code 128 | return retval -------------------------------------------------------------------------------- /unittests/custom_firmware/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include "gpio_funcs.h" 3 | #include 4 | #include 5 | #include "sleep.h" 6 | 7 | #define SET_emu_rst 0 8 | #define SET_emu_dec_thr 1 9 | #define SET_emu_ctrl_data 2 10 | #define SET_emu_ctrl_mode 3 11 | #define SET_a_in 4 12 | #define SET_b_in 5 13 | #define SET_mode_in 6 14 | #define GET_c_out 7 15 | 16 | int main() { 17 | // character buffering 18 | u32 idx = 0; 19 | char rcv; 20 | char buf [32]; 21 | 22 | // command processing; 23 | u32 cmd; 24 | u32 arg1; 25 | u32 nargs = 0; 26 | 27 | if (init_GPIO() != 0) { 28 | xil_printf("GPIO Initialization Failed\r\n"); 29 | return XST_FAILURE; 30 | } 31 | 32 | while (1) { 33 | rcv = inbyte(); 34 | if ((rcv == ' ') || (rcv == '\t') || (rcv == '\r') || (rcv == '\n')) { 35 | // whitespace 36 | if (idx > 0) { 37 | buf[idx++] = '\0'; 38 | if (nargs == 0) { 39 | if (strcmp(buf, "HELLO") == 0) { 40 | xil_printf("Hello World!\r\n"); 41 | nargs = 0; 42 | } else if (strcmp(buf, "EXIT") == 0) { 43 | return 0; 44 | 45 | } else if (strcmp(buf, "SET_emu_rst") == 0) { 46 | cmd = SET_emu_rst; 47 | nargs++; 48 | 49 | } else if (strcmp(buf, "SET_emu_dec_thr") == 0) { 50 | cmd = SET_emu_dec_thr; 51 | nargs++; 52 | 53 | } else if (strcmp(buf, "SET_emu_ctrl_data") == 0) { 54 | cmd = SET_emu_ctrl_data; 55 | nargs++; 56 | 57 | } else if (strcmp(buf, "SET_emu_ctrl_mode") == 0) { 58 | cmd = SET_emu_ctrl_mode; 59 | nargs++; 60 | 61 | } else if (strcmp(buf, "SET_a_in") == 0) { 62 | cmd = SET_a_in; 63 | nargs++; 64 | 65 | } else if (strcmp(buf, "SET_b_in") == 0) { 66 | cmd = SET_b_in; 67 | nargs++; 68 | 69 | } else if (strcmp(buf, "SET_mode_in") == 0) { 70 | cmd = SET_mode_in; 71 | nargs++; 72 | 73 | } else if (strcmp(buf, "GET_c_out") == 0) { 74 | xil_printf("%0d\r\n", get_c_out()); 75 | nargs = 0; 76 | 77 | } else { 78 | xil_printf("ERROR: Unknown command\r\n"); 79 | } 80 | } else if (nargs == 1) { 81 | sscanf(buf, "%lu", &arg1); 82 | 83 | if (cmd == SET_emu_rst) { 84 | set_emu_rst(arg1) 85 | ; 86 | 87 | xil_printf("0\r\n"); 88 | 89 | } else if (cmd == SET_emu_dec_thr) { 90 | set_emu_dec_thr(arg1) 91 | ; 92 | 93 | xil_printf("0\r\n"); 94 | 95 | } else if (cmd == SET_emu_ctrl_data) { 96 | set_emu_ctrl_data(arg1) 97 | ; 98 | 99 | xil_printf("0\r\n"); 100 | 101 | } else if (cmd == SET_emu_ctrl_mode) { 102 | set_emu_ctrl_mode(arg1) 103 | ; 104 | 105 | xil_printf("0\r\n"); 106 | 107 | } else if (cmd == SET_a_in) { 108 | set_a_in(arg1) 109 | ; 110 | 111 | xil_printf("0\r\n"); 112 | 113 | } else if (cmd == SET_b_in) { 114 | set_b_in(arg1) 115 | ; 116 | 117 | xil_printf("0\r\n"); 118 | 119 | } else if (cmd == SET_mode_in) { 120 | set_mode_in(arg1) 121 | ; 122 | 123 | xil_printf("0\r\n"); 124 | 125 | } 126 | nargs = 0; 127 | } 128 | } 129 | idx = 0; 130 | } else { 131 | // load next character 132 | buf[idx++] = rcv; 133 | } 134 | } 135 | 136 | return 0; 137 | } 138 | -------------------------------------------------------------------------------- /anasymod/plugins.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from anasymod.sources import Sources, VerilogHeader, VerilogSource, VHDLSource 4 | from anasymod.defines import Define 5 | from anasymod.enums import ConfigSections 6 | from anasymod.base_config import BaseConfig 7 | 8 | class Plugin(): 9 | def __init__(self, cfg_file, prj_root, build_root, name): 10 | self.args = None 11 | 12 | self._cfg_file = cfg_file 13 | self._prj_root = prj_root 14 | self._build_root = build_root 15 | self._srccfg_path = os.path.join(self._prj_root, r"source.yaml") 16 | self._name = name 17 | self._defines = [] 18 | self.generator_sources = [] 19 | self._verilog_sources = [] 20 | """:type : List[VerilogSource]""" 21 | 22 | self._verilog_headers = [] 23 | """:type : List[VerilogHeader]""" 24 | 25 | self._vhdl_sources = [] 26 | """:type : List[VHDLSource]""" 27 | 28 | # List of includes that need to be added to source files generated via ANASYMOD 29 | self.cfg = Config(cfg_file=self._cfg_file) 30 | 31 | self.include_statements = [] 32 | 33 | 34 | #### User Functions #### 35 | 36 | def models(self): 37 | """ 38 | Runs source code generator. 39 | """ 40 | raise NotImplementedError() 41 | 42 | def set_option(self, name, value=None): 43 | func = getattr(self, name) 44 | if callable(func): 45 | if value is True or None: 46 | func() 47 | elif not value: 48 | pass 49 | else: 50 | func(value) 51 | else: 52 | raise Exception(f'ERROR: Provided option:{name} is not supported for this generator.') 53 | 54 | #### Utility Functions #### 55 | 56 | def _add_source(self, source: Sources): 57 | if isinstance(source, VerilogSource): 58 | self._verilog_sources.append(source) 59 | if isinstance(source, VerilogHeader): 60 | self._verilog_headers.append(source) 61 | if isinstance(source, VHDLSource): 62 | self._vhdl_sources.append(source) 63 | 64 | def _add_define(self, define: Define): 65 | self._defines.append(define) 66 | 67 | def _dump_defines(self): 68 | return self._defines 69 | 70 | def _dump_verilog_sources(self): 71 | return self._verilog_sources 72 | 73 | def _dump_verilog_headers(self): 74 | return self._verilog_headers 75 | 76 | def _dump_vhdl_sources(self): 77 | return self._vhdl_sources 78 | 79 | def _setup_sources(self): 80 | """ 81 | Add Source objects that are specific to MSDSL 82 | """ 83 | raise NotImplementedError() 84 | 85 | def _setup_defines(self): 86 | """ 87 | Add Define objects that are specific to MSDSL 88 | """ 89 | raise NotImplementedError() 90 | 91 | def _parse_args(self): 92 | """ 93 | Read command line arguments. This supports convenient usage from command shell e.g.: 94 | python analysis.py -i filter --models --sim --view 95 | """ 96 | pass 97 | 98 | def _return_args(self): 99 | return self.args 100 | 101 | def _set_generator_sources(self, generator_sources: list): 102 | """ 103 | Set, which functional models shall be generated via the msdsl plugin. This works by setting the class instance 104 | attribute self.generator_sources. 105 | 106 | :param generator_sources: List of source objects specific to the generator 107 | """ 108 | 109 | if any(isinstance(i, Sources) for i in generator_sources): # Make sure all elements in the list are of type Sources 110 | [i.expand_paths() for i in generator_sources] 111 | self.generator_sources = generator_sources 112 | else: 113 | raise Exception(f'ERROR: Format for argument generator_sources is incorrect, expected list, got:{type(generator_sources)}') 114 | 115 | class Config(BaseConfig): 116 | """ 117 | Container to store all config attributes. 118 | """ 119 | 120 | def __init__(self, cfg_file): 121 | super().__init__(cfg_file=cfg_file, section=ConfigSections.PLUGIN) -------------------------------------------------------------------------------- /anasymod/sim_ctrl/uart_zynq_ctrlinfra.py: -------------------------------------------------------------------------------- 1 | import os 2 | from anasymod.sim_ctrl.ctrlinfra import ControlInfrastructure 3 | from anasymod.structures.module_uartsimctrl import ModuleUARTSimCtrl 4 | from anasymod.structures.module_regmapsimctrl import ModuleRegMapSimCtrl 5 | from anasymod.sources import VerilogSource, BDFile, FirmwareFile 6 | from anasymod.files import get_from_anasymod 7 | from anasymod.structures.structure_config import StructureConfig 8 | from anasymod.structures.firmware_gpio import FirmwareGPIO 9 | from anasymod.structures.uart_zynq_firmware_appcode import UartZynqFirmwareAppCode 10 | #from anasymod.targets import Config as tcfg 11 | 12 | class UARTControlInfrastructure(ControlInfrastructure): 13 | def __init__(self, prj_cfg, scfg: StructureConfig, plugin_includes, tcfg): 14 | super().__init__(prj_cfg=prj_cfg, plugin_includes=plugin_includes) 15 | self.scfg = scfg 16 | self.tcfg = tcfg 17 | 18 | # Initialize internal variables 19 | self._simctrlregmap_path = os.path.join(prj_cfg.build_root, 'gen_ctrlregmap.sv') 20 | 21 | #TODO: add path to elf file and add structure for storing ctrl ifc dependent files, 22 | # also including the BD; later test if .tcl script for creating BD would be 23 | # beneficial/at least there should be a script for creating the .bd file for a 24 | # new Vivado version, also add binary path to xsct interface 25 | 26 | def gen_ctrlwrapper(self, str_cfg: StructureConfig, content): 27 | """ 28 | Generate RTL design for control infrastructure. This will generate the register map, add the 29 | block diagram including the zynq PS and add the firmware running on the zynq PS. 30 | """ 31 | 32 | # Generate simulation control wrapper and add to target sources 33 | with (open(self._simctrlwrap_path, 'w')) as ctrl_file: 34 | ctrl_file.write(ModuleUARTSimCtrl(scfg=self.scfg).render()) 35 | 36 | content.verilog_sources += [VerilogSource(files=self._simctrlwrap_path, name='simctrlwrap')] 37 | 38 | def gen_ctrl_infrastructure(self, content): 39 | """ 40 | Generate RTL design for FPGA specific control infrastructure, depending on the interface 41 | selected for communication. For UART_ZYNQ control a register map, ZYNQ CPU SS block 42 | diagram and the firmware running on the zynq PS need to be handled. 43 | """ 44 | 45 | # Generate register map according to IO settings stored in structure config and add to target sources 46 | with (open(self._simctrlregmap_path, 'w')) as ctrl_file: 47 | ctrl_file.write(ModuleRegMapSimCtrl(scfg=self.scfg).render()) 48 | 49 | content.verilog_sources += [VerilogSource(files=self._simctrlregmap_path, name='simctrlregmap')] 50 | 51 | # Generate Hardware Abstraction Layer according to control signals 52 | # specified in the simctrl.yaml file and add to sources. 53 | 54 | gpio_fw = FirmwareGPIO(scfg=self.scfg) 55 | 56 | # Write header code 57 | gpio_hdr = os.path.join(self.pcfg.build_root, 'gpio_funcs.h') 58 | with open(gpio_hdr, 'w') as f: 59 | f.write(gpio_fw.hdr_text) 60 | content.firmware_files += [FirmwareFile(files=gpio_hdr, name='gpio_hdr')] 61 | 62 | # Write implementation code 63 | gpio_src = os.path.join(self.pcfg.build_root, 'gpio_funcs.c') 64 | with open(gpio_src, 'w') as f: 65 | f.write(gpio_fw.src_text) 66 | content.firmware_files += [FirmwareFile(files=gpio_src, name='gpio_src')] 67 | 68 | # Generate application code for UART_ZYNQ control, if no custom code is provided 69 | if not self.tcfg.custom_zynq_firmware: 70 | appcode = UartZynqFirmwareAppCode(scfg=self.scfg) 71 | # Write application code and add to firmware files 72 | appcode_src = os.path.join(self.pcfg.build_root, 'main.c') 73 | with open(appcode_src, 'w') as f: 74 | f.write(appcode.src_text) 75 | content.firmware_files += [FirmwareFile(files=appcode_src, name='appcode_src')] 76 | 77 | def add_ip_cores(self, scfg, ip_dir): 78 | """ 79 | Configures and adds IP cores that are necessary for selected IP cores. VIO IP core is configured and added. 80 | :return rendered template for configuring a vio IP core 81 | """ 82 | return [] -------------------------------------------------------------------------------- /anasymod/emu/xsct_emu.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | import re 3 | 4 | from pathlib import Path 5 | 6 | from anasymod.generators.xsct import XSCTTCLGenerator 7 | 8 | from anasymod.templates.xsct_build import TemplXSCTBuild 9 | from anasymod.templates.xsct_program import TemplXSCTProgram 10 | from anasymod.config import EmuConfig 11 | 12 | class XSCTEmulation(XSCTTCLGenerator): 13 | """ 14 | Generate and execute Vivado TCL scripts to generate a bitstream, run an emulation of FPGA for non-interactive mode, 15 | or launch an FPGA emulation for interactive mode and pass the handle for interactive control. 16 | """ 17 | 18 | def __init__(self, pcfg: EmuConfig, top_module, project_root, content): 19 | super().__init__(pcfg=pcfg) 20 | self.top_module = top_module 21 | self.project_root = project_root 22 | self.content = content 23 | 24 | self.err_str = re.compile('^(Failed)') 25 | 26 | @property 27 | def impl_dir(self): 28 | return ( 29 | Path(self.project_root) / 30 | f'{self.pcfg.vivado_config.project_name}.runs' / 31 | 'impl_1' 32 | ) 33 | 34 | @property 35 | def bit_path(self): 36 | return self.impl_dir / f'{self.top_module}.bit' 37 | 38 | @property 39 | def tcl_path(self): 40 | if self.pcfg.board.is_ultrascale: 41 | return self.impl_dir / 'psu_init.tcl' 42 | else: 43 | return self.impl_dir / 'ps7_init.tcl' 44 | 45 | @property 46 | def hw_path(self): 47 | if self.pcfg.xsct_config.version_year < 2020: 48 | return self.impl_dir / f'{self.top_module}.sysdef' 49 | else: 50 | return self.impl_dir / f'{self.top_module}.xsa' 51 | 52 | def build(self, create=True, copy_files=True, build=True): 53 | # determine SDK path 54 | sdk_path = (Path(self.project_root) / 55 | f'{self.pcfg.vivado_config.project_name}.sdk') 56 | 57 | # clear the SDK directory 58 | if create: 59 | shutil.rmtree(sdk_path, ignore_errors=True) 60 | sdk_path.mkdir(exist_ok=True, parents=True) 61 | 62 | # copy over the firmware sources 63 | if copy_files: 64 | src_path = sdk_path / 'sw' / 'src' 65 | src_path.mkdir(exist_ok=True, parents=True) 66 | for src in self.content.firmware_files: 67 | if src.files is not None: 68 | for file_ in src.files: 69 | shutil.copy(str(file_), str(src_path / Path(file_).name)) 70 | 71 | # determine the processor name 72 | if self.pcfg.board.is_ultrascale: 73 | proc_name = 'psu_cortexa53_0' 74 | else: 75 | proc_name = 'ps7_cortexa9_0' 76 | 77 | # generate the build script 78 | self.write( 79 | TemplXSCTBuild( 80 | sdk_path=sdk_path, 81 | hw_path=self.hw_path, 82 | version_year=self.pcfg.xsct_config.version_year, 83 | version_number=self.pcfg.xsct_config.version_number, 84 | proc_name=proc_name, 85 | create=create, 86 | build=build 87 | ).text 88 | ) 89 | 90 | # run the build script while checking for errors 91 | err_str = re.compile(r'(: error:)|(make.*: \*\*\* .* Error \d+)') 92 | self.run('sdk.tcl', err_str=err_str) 93 | 94 | def program(self, **kwargs): 95 | # determine SDK path 96 | sdk_path = (Path(self.project_root) / 97 | f'{self.pcfg.vivado_config.project_name}.sdk') 98 | 99 | # generate the build script 100 | self.write( 101 | TemplXSCTProgram( 102 | sdk_path=sdk_path, 103 | bit_path=self.bit_path, 104 | hw_path=self.hw_path, 105 | tcl_path=self.tcl_path, 106 | is_ultrascale=self.pcfg.board.is_ultrascale, 107 | xsct_install_dir=self.pcfg.xsct_config.xsct_install_dir, 108 | no_rev_check=self.pcfg.board.no_rev_check, 109 | pcfg=self.pcfg, 110 | **kwargs 111 | ).text 112 | ) 113 | 114 | # run the programming script. xsct appears to return an error code 115 | # when the FPGA board is not plugged in or is not powered up, so 116 | # parsing for errors doesn't appear to be necessary in this case) 117 | self.run('program.tcl', err_str=self.err_str) 118 | -------------------------------------------------------------------------------- /anasymod/structures/module_emu_clks.py: -------------------------------------------------------------------------------- 1 | from anasymod.templates.templ import JinjaTempl 2 | from anasymod.config import EmuConfig 3 | from anasymod.generators.gen_api import SVAPI, ModuleInst 4 | from anasymod.structures.structure_config import StructureConfig 5 | from anasymod.sim_ctrl.datatypes import DigitalSignal 6 | 7 | 8 | class ModuleEmuClks(JinjaTempl): 9 | def __init__(self, scfg: StructureConfig, pcfg: EmuConfig): 10 | super().__init__(trim_blocks=True, lstrip_blocks=True) 11 | 12 | gated_clks = [] 13 | 14 | ##################################################### 15 | # Create module interface 16 | ##################################################### 17 | self.module_ifc = SVAPI() 18 | 19 | module = ModuleInst(api=self.module_ifc, name="gen_emu_clks") 20 | module.add_input(scfg.emu_clk_2x) 21 | module.add_output(scfg.emu_clk) 22 | 23 | for derived_clk in scfg.clk_derived: 24 | if derived_clk.abspath_gated_clk is not None: 25 | gated_clks.append(derived_clk.name) 26 | 27 | # add IOs for default oscillator if used 28 | self.use_default_oscillator = scfg.use_default_oscillator 29 | if scfg.use_default_oscillator: 30 | module.add_input(DigitalSignal(name=f'clk_val_default_osc', width=1, abspath='')) 31 | module.add_output(DigitalSignal(name=f'clk_default_osc', width=1, abspath='')) 32 | 33 | for gated_clk in gated_clks: 34 | module.add_input(DigitalSignal(name=f'clk_val_{gated_clk}', width=1, abspath='')) 35 | module.add_output(DigitalSignal(name=f'clk_{gated_clk}', width=1, abspath='')) 36 | 37 | module.generate_header() 38 | 39 | ##################################################### 40 | # Generate other clks 41 | ##################################################### 42 | self.generated_clks = SVAPI() 43 | 44 | if gated_clks: 45 | for gated_clk in gated_clks: 46 | self.generated_clks.gen_signal(DigitalSignal(name=f'clk_unbuf_{gated_clk}', width=1, abspath=''), default_value=0) 47 | self.generated_clks.writeln(f'always @(posedge emu_clk_2x) begin') 48 | self.generated_clks.indent() 49 | for gated_clk in gated_clks: 50 | self.generated_clks.writeln(f"if (emu_clk_unbuf == 1'b0) begin") 51 | self.generated_clks.indent() 52 | self.generated_clks.writeln(f'clk_unbuf_{gated_clk} <= clk_val_{gated_clk};') 53 | self.generated_clks.dedent() 54 | self.generated_clks.writeln(f'end else begin') 55 | self.generated_clks.indent() 56 | self.generated_clks.writeln(f"clk_unbuf_{gated_clk} <= clk_unbuf_{gated_clk};") 57 | self.generated_clks.dedent() 58 | self.generated_clks.writeln(f'end') 59 | self.generated_clks.dedent() 60 | self.generated_clks.writeln(f'end') 61 | self.generated_clks.writeln(f'') 62 | self.generated_clks.writeln(f'`ifndef SIMULATION_MODE_MSDSL') 63 | self.generated_clks.indent() 64 | for k, gated_clk in enumerate(gated_clks): 65 | self.generated_clks.writeln(f'BUFG buf_{k} (.I(clk_unbuf_{gated_clk}), .O(clk_{gated_clk}));') 66 | self.generated_clks.dedent() 67 | self.generated_clks.writeln(f'`else') 68 | self.generated_clks.indent() 69 | for gated_clk in gated_clks: 70 | self.generated_clks.writeln(f'assign clk_{gated_clk} = clk_unbuf_{gated_clk};') 71 | self.generated_clks.dedent() 72 | self.generated_clks.writeln(f'`endif') 73 | 74 | TEMPLATE_TEXT = ''' 75 | `timescale 1ns/1ps 76 | 77 | `default_nettype none 78 | 79 | {{subst.module_ifc.text}} 80 | 81 | // generate emu_clk 82 | logic emu_clk_unbuf = 0; 83 | 84 | always @(posedge emu_clk_2x) begin 85 | emu_clk_unbuf <= ~emu_clk_unbuf; 86 | end 87 | `ifndef SIMULATION_MODE_MSDSL 88 | BUFG buf_emu_clk (.I(emu_clk_unbuf), .O(emu_clk)); 89 | `else 90 | assign emu_clk = emu_clk_unbuf; 91 | `endif 92 | 93 | {% if subst.use_default_oscillator %} 94 | // Handle default oscillator 95 | logic clk_unbuf_default_osc = 0; 96 | always @(posedge emu_clk_2x) begin 97 | clk_unbuf_default_osc <= (~emu_clk_unbuf) & clk_val_default_osc; 98 | end 99 | `ifndef SIMULATION_MODE_MSDSL 100 | BUFG buf_default_osc (.I(clk_unbuf_default_osc), .O(clk_default_osc)); 101 | `else 102 | assign clk_default_osc = clk_unbuf_default_osc; 103 | `endif 104 | {% endif %} 105 | 106 | // generate other clocks 107 | {{subst.generated_clks.text}} 108 | endmodule 109 | 110 | `default_nettype wire 111 | ''' 112 | 113 | def main(): 114 | print(ModuleEmuClks(scfg=StructureConfig(prj_cfg=EmuConfig(root='test', cfg_file=''))).render()) 115 | 116 | if __name__ == "__main__": 117 | main() 118 | --------------------------------------------------------------------------------