├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── Makefile.vcs ├── README ├── amd_versal2_demo.cc ├── apb_timer.v ├── debugdev.cc ├── debugdev.h ├── demo-dma.cc ├── demo-dma.h ├── docs ├── lmac-demos.md └── zynq-7000-getting-started-guide.md ├── files-lmac2.mk ├── files-lmac3.mk ├── iconnect.h ├── lmac3_wrapper_top.v ├── lmac_wrapper_top.v ├── packages └── ipxact │ ├── le_wiz │ └── components │ │ └── lmac_wrapper_top │ │ └── 1.0 │ │ └── lmac_wrapper_top.1.0.xml │ └── xilinx.com │ ├── demos │ └── zynqmp_lmac2_demo │ │ └── 1.0 │ │ ├── zynqmp_lmac2_demo.1.0.xml │ │ ├── zynqmp_lmac2_demo.design.1.0.xml │ │ └── zynqmp_lmac2_demo.designcfg.1.0.xml │ └── systemctlm-cosim-demo │ ├── axidma_mm2s │ └── 1.0 │ │ └── axidma_mm2s.1.0.xml │ ├── axidma_s2mm │ └── 1.0 │ │ └── axidma_s2mm.1.0.xml │ ├── iconnect │ └── 1.0 │ │ └── iconnect.1.0.xml │ └── tlm_xgmii_phy │ └── 1.0 │ ├── tlm_xgmii_phy.1.0.xml │ ├── tlm_xgmii_phy.design.1.0.xml │ └── tlm_xgmii_phy.designcfg.1.0.xml ├── pcie-ats-demo ├── pcie-acc-md5sum-vfio.cc ├── pcie-acc.h ├── pcie-ats-demo.cc ├── pcie-ats-demo.md └── test-pcie-ats-demo-vfio.cc ├── pcie └── versal │ ├── cpm-qdma-demo.cc │ └── cpm-qdma-demos.md ├── riscv_virt_lmac2_demo.cc ├── riscv_virt_lmac3_demo.cc ├── sysc_verilog_top.sv ├── tlm-xgmii-phy.h ├── tlm2apb-bridge.h ├── trace.cc ├── trace.h ├── versal_demo.cc ├── versal_mrmac_demo.cc ├── versal_net_cdx_stub.cc ├── versal_net_cdx_stub.md ├── xilinx-axidma.cc ├── xilinx-axidma.h ├── zynq_demo.cc ├── zynqmp_demo.cc ├── zynqmp_lmac2_demo.cc ├── zynqmp_lmac2_ipxact_demo.txt ├── zynqmp_lmac3_demo.cc └── zynqmp_vcs_demo.cc /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *_demo 4 | .config.mk 5 | trace.vcd 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libsystemctlm-soc"] 2 | path = libsystemctlm-soc 3 | url = ../libsystemctlm-soc.git 4 | [submodule "LMAC_CORE2"] 5 | path = LMAC_CORE2 6 | url = ../../lewiz-support/LMAC_CORE2.git 7 | [submodule "LMAC_CORE3"] 8 | path = LMAC_CORE3 9 | url = ../../lewiz-support/LMAC_CORE3.git 10 | [submodule "pcie-model"] 11 | path = pcie-model 12 | url = ../pcie-model.git 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | See libsystemctlm-soc/LICENSE for licensing details for libsystemctlm-soc. 2 | 3 | All other demo files are distributed under the MIT license. 4 | https://en.wikipedia.org/wiki/MIT_License 5 | -------------------------------------------------------------------------------- /Makefile.vcs: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2021 Tianrui Wei . 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | 22 | # flags for synopsys tools 23 | CC ?= gcc 24 | CXX ?= g++ 25 | SNPS_FLAGS = -full64 -cpp $(CXX) -cc $(CC) -kdb -lca 26 | SNPS_VFLAGS = -debug_acc+r+w+dmptf -debug_region+cell+encrypt 27 | CPPFLAGS += -I${PWD}/csrc/sysc/include -I${VCS_HOME}/etc/systemc/tlm/tli 28 | CPPFLAGS += -DTLI_BYTE_VIEW_DEBUG -DVCS -I${VCS_HOME}/include/systemc232 29 | CPPFLAGS += -I${VCS_HOME}/include -I${VCS_HOME}/include/cosim/bf 30 | 31 | CFLAGS += -fPIC -g -Og -m64 32 | CXXFLAGS += -fPIC -g -Og -m64 33 | 34 | # path for libremote port 35 | LIBSOC_PATH=libsystemctlm-soc 36 | LIBSOC_ZYNQMP_PATH=$(LIBSOC_PATH)/soc/xilinx/zynqmp 37 | LIBRP_PATH=$(LIBSOC_PATH)/libremote-port 38 | 39 | # include files for lib remote port 40 | CPPFLAGS += -I $(LIBRP_PATH) -I $(LIBSOC_PATH) 41 | 42 | #include header files in this directory 43 | CPPFLAGS += -I . -I $(LIBSOC_ZYNQMP_PATH) 44 | 45 | RP_C_FILES = $(LIBRP_PATH)/safeio.c \ 46 | $(LIBRP_PATH)/remote-port-proto.c \ 47 | $(LIBRP_PATH)/remote-port-sk.c 48 | 49 | RP_CXX_FILES = $(LIBRP_PATH)/remote-port-tlm.cc \ 50 | $(LIBRP_PATH)/remote-port-tlm-memory-master.cc \ 51 | $(LIBRP_PATH)/remote-port-tlm-ats.cc \ 52 | $(LIBRP_PATH)/remote-port-tlm-pci-ep.cc \ 53 | $(LIBRP_PATH)/remote-port-tlm-memory-slave.cc \ 54 | $(LIBRP_PATH)/remote-port-tlm-wires.cc 55 | 56 | COSIM_SYSC_FILES = debugdev.cc \ 57 | demo-dma.cc \ 58 | $(LIBSOC_PATH)/tests/test-modules/memory.cc \ 59 | trace.cc \ 60 | zynqmp_vcs_demo.cc \ 61 | $(LIBSOC_ZYNQMP_PATH)/xilinx-zynqmp.cc 62 | 63 | CXX_FILES = $(RP_CXX_FILES) $(COSIM_SYSC_FILES) 64 | C_FILES = $(RP_C_FILES) 65 | 66 | TARGET = zynqmp_vcs_demo 67 | 68 | comp: uvm sysc_verilog comp_c libsc_hier.so 69 | mkdir work -p 70 | echo "compiling c++ files" 71 | vcs $(MAKE_PARALLEL) -sysc $(SNPS_FLAGS) libsc_hier.so -sysc=show_sc_main -top sc_main -ntb_opts uvm -debug_access+all -timescale=1ps/1fs -o $(TARGET) 72 | 73 | sysc_verilog: sysc_verilog_top.sv 74 | vlogan $(SNPS_FLAGS) $(SNPS_VFLAGS) -sverilog -sysc -sysc=opt_if -sysc=gen_portmap sysc_verilog_top.sv -sc_model sysc_verilog_top 75 | vlogan $(SNPS_FLAGS) $(SNPS_VFLAGS) -sverilog -sysc -sysc=opt_if sysc_verilog_top.sv -sc_model sysc_verilog_top -sc_portmap sysc_verilog_top.portmap 76 | 77 | # TODO: finer grain control 78 | comp_c: $(CXX_FILES) $(C_FILES) 79 | syscan $(SNPS_FLAGS) -cflags "$(CPPFLAGS) $(CXXFLAGS)" $(CXX_FILES) 80 | $(CC) -c $(CPPFLAGS) $(CFLAGS) $(C_FILES) 81 | $(CC) -g -fPIC -shared -o libsc_hier.so *.o 82 | 83 | uvm: 84 | vlogan $(SNPS_FLAGS) $(SNPS_VFLAGS) -sverilog -ntb_opts uvm 85 | 86 | clean: 87 | $(RM) -rf AN.DB csrc $(TARGET).daidir $(TARGET) work ucli.key vc_hdrs.h DVEfiles 88 | $(RM) -rf *.vpd dir1 *.o *.d *.so tli_uvm_mem_data.sv *.log *.portmap 89 | $(RM) -rf *.error 64 verdiLog novas.conf work.lib++ verdi_config_file 90 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | TLM-COSIM-DEMO 2 | --------------------------------------- 3 | This contains a small SystemC/TLM-2.0 based subsystem for demo purposes. 4 | It has an interconnect connecting a remote-port attached QEMU 5 | instance, a demo/debug-device, a small DMA and if verilator is available 6 | a timer. Note that the remote-port instance connecting to QEMU 7 | can serve multiple QEMU instances. In fact, this demo can run 8 | connected to the ZynqMP platform with 2 external QEMU instances 9 | (APU/RPU and PMU). All of these instances can access the 10 | TLM world. 11 | 12 | The demo/debug-device is used to read out System-C time, output 13 | debug trace/events and to end the simulation. 14 | 15 | The DMA is used to demonstrate the bus mastering capabilities of the 16 | TLM world back into QEMU via remote-port. 17 | 18 | The timer is a minimalistic APB connected timer written in 19 | verilog. If verilator is available, this timer can be hooked 20 | into the simulation. 21 | For TLM to be able to talk to the APB timer, a TLM-2-APB bridge 22 | was written in System-C. 23 | 24 | BUILD 25 | --------------------------------------- 26 | Before building you will need to ensure that you have SystemC and SCML 27 | available. 28 | 29 | The demo was prepared assuming the following versions: 30 | SystemC: 2.3.2 31 | 32 | The Makefile assumes that both are installed in the directories below: 33 | SystemC: /usr/local/systemc-2.3.2/ 34 | 35 | If you have them installed in different directories point the Makefile to the 36 | correct directory by setting the variables SYSTEMC. 37 | 38 | You will also need to clone the libremote-port submodule, by running: 39 | $ git submodule update --init libsystemctlm-soc 40 | 41 | Also make sure to have the header in the default search 42 | directory list for your version of CPP (the header is required by the 43 | pcie-model submodule). On a Ubuntu LTS system the header can be installed 44 | through the `linux-libc-dev` packages. 45 | $ sudo apt-get install linux-libc-dev 46 | 47 | Once everything is installed you can just run make. If SystemC is in 48 | a different directory then mentioned about you will need to specify the 49 | directory by setting the variables mentioned above. 50 | 51 | You can also configure the build by creating a .config.mk file. 52 | There are other options that can be set, e.g: 53 | HAVE_VERILOG=n 54 | HAVE_VERILOG_VERILATOR=n 55 | HAVE_VERILOG_VCS=n 56 | 57 | RUN 58 | --------------------------------------- 59 | When running you will need to make sure the program can link to your 60 | SystemC/TLM libraries. You will also need to give arguments to the application. 61 | The first argument points to the QEMU machine-path to use. The second argument 62 | is the icount value to use. The arguments should line up with the QEMU command 63 | line arguments. 64 | 65 | A Versal example: 66 | In one terminal, in the demo directory 67 | LD_LIBRARY_PATH=/usr/local/systemc-2.3.2/lib-linux64/ ./versal_demo \ 68 | unix:/tmp/qemu/qemu-rport-_amba@0_cosim@0 10000 69 | 70 | A ZynqMP example: 71 | In one terminal, in the demo directory 72 | LD_LIBRARY_PATH=/usr/local/systemc-2.3.2/lib-linux64/ ./zynqmp_demo \ 73 | unix:./qemu-tmp/qemu-rport-_amba@0_cosim@0 10000 74 | 75 | A Zynq-7000 example: 76 | LD_LIBRARY_PATH=/usr/local/systemc-2.3.2/lib-linux64/ ./zynq_demo \ 77 | unix:./qemu-tmp/qemu-rport-_cosim@0 1000000 78 | 79 | In another terminal you will need to start up the PS. In this case we are going 80 | to start up a PetaLinux QEMU session and use the Linux kernel to probe the 81 | SystemC side. You could also start up your own kernel with the required drivers 82 | or a baremetal application. 83 | 84 | See here for instructions on how to start the PetaLinux QEMU session: 85 | http://www.wiki.xilinx.com/Co-simulation 86 | 87 | IP-XACT DEMO 88 | --------------------------------------- 89 | This repository also contains a demo where a QEMU / SystemC co-simulation 90 | is automatically generated from an IP-XACT description. More information 91 | about this demo and instructions for how to launch it manually can be 92 | found inside the 'zynqmp_lmac2_ipxact_demo.txt' file. 93 | -------------------------------------------------------------------------------- /amd_versal2_demo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Top level of the amd_versal2 cosim example. 3 | * 4 | * Copyright (c) 2023 Advanced Micro Devices Inc. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #define SC_INCLUDE_DYNAMIC_PROCESSES 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "systemc.h" 33 | #include "tlm_utils/simple_initiator_socket.h" 34 | #include "tlm_utils/simple_target_socket.h" 35 | #include "tlm_utils/tlm_quantumkeeper.h" 36 | 37 | using namespace sc_core; 38 | using namespace sc_dt; 39 | using namespace std; 40 | 41 | #include "trace.h" 42 | #include "soc/interconnect/iconnect.h" 43 | #include "debugdev.h" 44 | #include "soc/amd/amd-versal2/amd-versal2.h" 45 | #include "memory.h" 46 | #include "demo-dma.h" 47 | #include "wiredev.h" 48 | #include "wire-loopback.h" 49 | #include "tlm-bridges/tlm2apb-bridge.h" 50 | 51 | #define RAM_SIZE (2 * 1024 * 1024) 52 | 53 | #define NR_MASTERS 6 54 | #define NR_DEVICES 11 55 | 56 | SC_MODULE(Top) 57 | { 58 | iconnect bus; 59 | amd_versal2 versal2; 60 | debugdev debug; 61 | debugdev debug2; 62 | demodma dma; 63 | 64 | memory mem0; 65 | 66 | wiredev wreg_out_en_emio0; 67 | wiredev wreg_out_en_emio1; 68 | wiredev wreg_out_emio2; 69 | wiredev wreg_out_en_emio2; 70 | wire_loopback wlb; 71 | wiredev wreg_pl_reset; 72 | 73 | tlm2apb_bridge *tlm2apb_tmr; 74 | 75 | sc_signal apbsig_timer_psel; 76 | sc_signal apbsig_timer_penable; 77 | sc_signal apbsig_timer_pwrite; 78 | sc_signal apbsig_timer_pready; 79 | sc_signal > apbsig_timer_paddr; 80 | sc_signal > apbsig_timer_pwdata; 81 | sc_signal > apbsig_timer_prdata; 82 | 83 | sc_clock *clk; 84 | sc_signal rst; 85 | 86 | SC_HAS_PROCESS(Top); 87 | 88 | void pull_reset(void) { 89 | /* Pull the reset signal. */ 90 | rst.write(true); 91 | wait(1, SC_US); 92 | rst.write(false); 93 | } 94 | 95 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 96 | sc_module(name), 97 | bus("bus"), 98 | versal2("versal2", sk_descr), 99 | debug("debugdev"), 100 | debug2("debugdev2"), 101 | dma("dma"), 102 | mem0("mem0", sc_time(1, SC_NS), RAM_SIZE), 103 | wreg_out_en_emio0("wreg_out_en_emio0", 32), 104 | wreg_out_en_emio1("wreg_out_en_emio1", 32), 105 | wreg_out_emio2("wreg_out_emio2", 32), 106 | wreg_out_en_emio2("wreg_out_en_emio2", 32), 107 | wlb("wlb", 32), 108 | wreg_pl_reset("wreg_pl_reset", versal2.pl_reset.size()), 109 | apbsig_timer_psel("apbtimer_psel"), 110 | apbsig_timer_penable("apbtimer_penable"), 111 | apbsig_timer_pwrite("apbtimer_pwrite"), 112 | apbsig_timer_pready("apbtimer_pready"), 113 | apbsig_timer_paddr("apbtimer_paddr"), 114 | apbsig_timer_pwdata("apbtimer_pwdata"), 115 | apbsig_timer_prdata("apbtimer_prdata"), 116 | rst("rst") 117 | { 118 | unsigned int i; 119 | 120 | clk = new sc_clock("clk", sc_time(10, SC_US)); 121 | tlm2apb_tmr = new tlm2apb_bridge 122 | ("tlm2apb-tmr-bridge"); 123 | 124 | m_qk.set_global_quantum(quantum); 125 | 126 | versal2.rst(rst); 127 | 128 | bus.memmap(0x80000120ULL, 0xC - 1, 129 | ADDRMODE_RELATIVE, -1, wreg_pl_reset.socket); 130 | bus.memmap(0x80000000ULL, 0x100 - 1, 131 | ADDRMODE_RELATIVE, -1, debug.socket); 132 | bus.memmap(0x80020000ULL, 0x10 - 1, 133 | ADDRMODE_RELATIVE, -1, tlm2apb_tmr->tgt_socket); 134 | bus.memmap(0x80000200ULL, 0x4 - 1, 135 | ADDRMODE_RELATIVE, -1, wreg_out_emio2.socket); 136 | bus.memmap(0x80000300ULL, 0x4 - 1, 137 | ADDRMODE_RELATIVE, -1, wreg_out_en_emio0.socket); 138 | bus.memmap(0x80000400ULL, 0x4 - 1, 139 | ADDRMODE_RELATIVE, -1, wreg_out_en_emio1.socket); 140 | bus.memmap(0x80000500ULL, 0x4 - 1, 141 | ADDRMODE_RELATIVE, -1, wreg_out_en_emio2.socket); 142 | bus.memmap(0xb0000000ULL, 0x100 - 1, 143 | ADDRMODE_RELATIVE, -1, debug2.socket); 144 | bus.memmap(0xb0010000ULL, 0x10 - 1, 145 | ADDRMODE_RELATIVE, -1, dma.tgt_socket); 146 | bus.memmap(0xb0020000ULL, RAM_SIZE - 1, 147 | ADDRMODE_RELATIVE, -1, mem0.socket); 148 | bus.memmap(0x0LL, UINT64_MAX - 1, 149 | ADDRMODE_RELATIVE, -1, *(versal2.s_pl_axi_fpd0)); 150 | 151 | // 152 | // Bus masters 153 | // 154 | versal2.m_fpd_axi_pl->bind(*(bus.t_sk[0])); 155 | versal2.m_lpd_axi_pl->bind(*(bus.t_sk[1])); 156 | versal2.m_pmxc_axi_noc0->bind(*(bus.t_sk[2])); 157 | versal2.m_fpd_axi_noc0->bind(*(bus.t_sk[3])); 158 | versal2.m_mmu_noc0->bind(*(bus.t_sk[4])); 159 | 160 | dma.init_socket.bind(*(bus.t_sk[5])); 161 | 162 | /* Connect the PL irqs to the irq_pl_to_ps wires. */ 163 | debug.irq[0](versal2.pl2ps_irq[0]); 164 | debug.irq[1](versal2.npi_irq[0]); 165 | dma.irq(versal2.pl2ps_irq[1]); 166 | 167 | /* Connect EMIO0 to EMIO1, so outputs / inputs can be 168 | * tested. */ 169 | for (i = 0; i < 32; i++) { 170 | wlb.wire_in[i](versal2.emio[0]->out[i]); 171 | wlb.wire_out[i](versal2.emio[1]->in[i]); 172 | } 173 | 174 | /* Connect EMIO2 outputs. */ 175 | for (i = 0; i < 32; i++) { 176 | wreg_out_emio2.wires_in[i](versal2.emio[2]->out[i]); 177 | } 178 | 179 | /* Connect output enable signals. */ 180 | for (i = 0; i < 32; i++) { 181 | wreg_out_en_emio0.wires_in[i]( 182 | versal2.emio[0]->out_enable[i]); 183 | wreg_out_en_emio1.wires_in[i]( 184 | versal2.emio[1]->out_enable[i]); 185 | wreg_out_en_emio2.wires_in[i]( 186 | versal2.emio[2]->out_enable[i]); 187 | } 188 | 189 | for(i = 0; i < versal2.pl_reset.size(); i++) { 190 | wreg_pl_reset.wires_in[i](versal2.pl_reset[i]); 191 | } 192 | 193 | // 194 | // Dummy timer for now 195 | // 196 | clk = new sc_clock("clk", sc_time(20, SC_US)); 197 | apbsig_timer_prdata = 0xeddebeef; 198 | apbsig_timer_pready = true; 199 | tlm2apb_tmr->clk(*clk); 200 | tlm2apb_tmr->psel(apbsig_timer_psel); 201 | tlm2apb_tmr->penable(apbsig_timer_penable); 202 | tlm2apb_tmr->pwrite(apbsig_timer_pwrite); 203 | tlm2apb_tmr->paddr(apbsig_timer_paddr); 204 | tlm2apb_tmr->pwdata(apbsig_timer_pwdata); 205 | tlm2apb_tmr->prdata(apbsig_timer_prdata); 206 | tlm2apb_tmr->pready(apbsig_timer_pready); 207 | 208 | /* Tie off any remaining unconnected signals. */ 209 | versal2.tie_off(); 210 | 211 | SC_THREAD(pull_reset); 212 | } 213 | 214 | private: 215 | tlm_utils::tlm_quantumkeeper m_qk; 216 | }; 217 | 218 | void usage(void) 219 | { 220 | cout << "tlm socket-path sync-quantum-ns" << endl; 221 | } 222 | 223 | int sc_main(int argc, char* argv[]) 224 | { 225 | Top *top; 226 | uint64_t sync_quantum; 227 | sc_trace_file *trace_fp = NULL; 228 | 229 | if (argc < 3) { 230 | sync_quantum = 10000; 231 | } else { 232 | sync_quantum = strtoull(argv[2], NULL, 10); 233 | } 234 | 235 | sc_set_time_resolution(1, SC_PS); 236 | 237 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 238 | 239 | if (argc < 3) { 240 | sc_start(1, SC_PS); 241 | sc_stop(); 242 | usage(); 243 | exit(EXIT_FAILURE); 244 | } 245 | 246 | trace_fp = sc_create_vcd_trace_file("trace"); 247 | trace(trace_fp, *top, top->name()); 248 | 249 | sc_start(); 250 | if (trace_fp) { 251 | sc_close_vcd_trace_file(trace_fp); 252 | } 253 | return 0; 254 | } 255 | -------------------------------------------------------------------------------- /apb_timer.v: -------------------------------------------------------------------------------- 1 | // Minimalistic Timer block. Part of C3P3u. 2 | // Copyright (c) 2010 Edgar E. Iglesias 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | module apb_slave_timer(clk, rst, 23 | psel, penable, pwrite, paddr, pwdata, prdata, 24 | pready, 25 | irq); 26 | input clk; 27 | input rst; 28 | 29 | input psel; 30 | input penable; 31 | input pwrite; 32 | input [15:0] paddr; 33 | input [31:0] pwdata; 34 | output reg [31:0] prdata; 35 | output reg pready; 36 | output irq; 37 | 38 | // bit 0 enable cntdown 39 | // bit 1 irq pending 40 | reg [1:0] tmr_cfg; 41 | reg [31:0] tmr_cnt; 42 | reg [31:0] tmr_div; 43 | reg [31:0] tmr_free_cnt; 44 | 45 | assign irq = tmr_cfg[1]; 46 | 47 | always @(posedge clk) begin 48 | tmr_free_cnt <= tmr_free_cnt + 1; 49 | 50 | if (tmr_cfg[0]) begin 51 | tmr_cnt <= tmr_cnt - 1; 52 | if (tmr_cnt == 0) begin 53 | // $display("timer hit, reloading %x\n", tmr_div); 54 | tmr_cnt <= tmr_div; 55 | tmr_cfg[1] <= 1; 56 | end 57 | end 58 | 59 | prdata <= 'bx; 60 | pready <= 0; 61 | if (psel) begin 62 | // We do single cycle accesses 63 | pready <= penable; 64 | if (penable && pwrite) begin 65 | case (paddr[15:2]) 66 | 0: begin 67 | tmr_cfg <= pwdata[1:0]; 68 | // When enabling the timer, reload 69 | // the divisor. 70 | if (tmr_cfg[0] ^ pwdata[0]) begin 71 | if (pwdata[0]) begin 72 | tmr_cnt <= tmr_div; 73 | end 74 | end 75 | end 76 | 77 | 1: tmr_cnt <= pwdata; 78 | 2: begin tmr_div <= pwdata; 79 | // $display("wirte %x to div", pwdata); 80 | end 81 | 3: tmr_free_cnt <= pwdata; 82 | endcase 83 | end 84 | case (paddr[15:2]) 85 | 0: prdata[1:0] <= tmr_cfg; 86 | 1: prdata <= tmr_cnt; 87 | 2: prdata <= tmr_div; 88 | 3: begin 89 | prdata <= tmr_free_cnt; 90 | end 91 | endcase 92 | end 93 | 94 | if (rst) begin 95 | tmr_free_cnt <= 0; 96 | tmr_cnt <= 0; 97 | tmr_div <= 0; 98 | tmr_cfg <= 0; 99 | end 100 | end 101 | endmodule 102 | -------------------------------------------------------------------------------- /debugdev.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * A demo/debug device. 3 | * 4 | * Copyright (c) 2013 Xilinx Inc. 5 | * Written by Edgar E. Iglesias 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #define SC_INCLUDE_DYNAMIC_PROCESSES 27 | 28 | #include 29 | 30 | #include "tlm_utils/simple_initiator_socket.h" 31 | #include "tlm_utils/simple_target_socket.h" 32 | 33 | using namespace sc_core; 34 | using namespace std; 35 | 36 | #include "debugdev.h" 37 | #include 38 | #include 39 | 40 | debugdev::debugdev(sc_module_name name) 41 | : sc_module(name), socket("socket") 42 | { 43 | socket.register_b_transport(this, &debugdev::b_transport); 44 | socket.register_transport_dbg(this, &debugdev::transport_dbg); 45 | } 46 | 47 | void debugdev::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) 48 | { 49 | tlm::tlm_command cmd = trans.get_command(); 50 | sc_dt::uint64 addr = trans.get_address(); 51 | unsigned char *data = trans.get_data_ptr(); 52 | unsigned int len = trans.get_data_length(); 53 | unsigned char *byt = trans.get_byte_enable_ptr(); 54 | unsigned int wid = trans.get_streaming_width(); 55 | 56 | if (byt != 0) { 57 | trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); 58 | return; 59 | } 60 | 61 | if (len > 4 || wid < len) { 62 | trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); 63 | return; 64 | } 65 | trans.set_response_status(tlm::TLM_OK_RESPONSE); 66 | 67 | // Pretend this is slow! 68 | delay += sc_time(1, SC_US); 69 | 70 | if (trans.get_command() == tlm::TLM_READ_COMMAND) { 71 | sc_time now = sc_time_stamp() + delay; 72 | uint32_t v = 0; 73 | 74 | switch (addr) { 75 | case 0: 76 | // cout << "read " << addr << " " << t << endl; 77 | v = now.to_seconds() * 1000 * 1000 * 1000; 78 | break; 79 | case 0xc: 80 | v = irq[0].read(); 81 | v |= irq[1].read() << 1; 82 | break; 83 | case 0x10: 84 | v = clock(); 85 | break; 86 | case 0xf0: 87 | trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE); 88 | break; 89 | case 0xf4: 90 | trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); 91 | break; 92 | default: 93 | break; 94 | } 95 | memcpy(data, &v, len); 96 | } else if (cmd == tlm::TLM_WRITE_COMMAND) { 97 | static sc_time old_ts = SC_ZERO_TIME, now, diff; 98 | 99 | now = sc_time_stamp() + delay; 100 | diff = now - old_ts; 101 | switch (addr) { 102 | case 0: 103 | cout << "TRACE: " << " " 104 | << hex << * (uint32_t *) data 105 | << " " << now << " diff=" << diff << "\n"; 106 | break; 107 | case 0x4: 108 | putchar(* (uint32_t *) data); 109 | break; 110 | case 0x8: 111 | cout << "STOP: " << " " 112 | << hex << * (uint32_t *) data 113 | << " " << now << "\n"; 114 | sc_stop(); 115 | exit(1); 116 | break; 117 | case 0xc: 118 | irq[0].write(data[0] & 1); 119 | irq[1].write((data[0] & 2) >> 1); 120 | break; 121 | case 0xf0: 122 | trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE); 123 | break; 124 | case 0xf4: 125 | trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); 126 | break; 127 | default: 128 | break; 129 | } 130 | old_ts = now; 131 | } 132 | 133 | } 134 | 135 | unsigned int debugdev::transport_dbg(tlm::tlm_generic_payload& trans) 136 | { 137 | unsigned int len = trans.get_data_length(); 138 | return len; 139 | } 140 | 141 | void debugdev::before_end_of_elaboration() 142 | { 143 | for (int i = 0; i < NUM_DBG_IRQ; i++) { 144 | if (irq[i].size() == 0) { 145 | cout << "irq: " << i << " tied off" << endl; 146 | irq[i](irq_tieoff[i]); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /debugdev.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Xilinx Inc. 3 | * Written by Edgar E. Iglesias. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | #define NUM_DBG_IRQ 2 25 | 26 | class debugdev 27 | : public sc_core::sc_module 28 | { 29 | public: 30 | tlm_utils::simple_target_socket socket; 31 | sc_out irq[NUM_DBG_IRQ]; 32 | 33 | debugdev(sc_core::sc_module_name name); 34 | virtual void b_transport(tlm::tlm_generic_payload& trans, 35 | sc_time& delay); 36 | virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans); 37 | 38 | void before_end_of_elaboration(); 39 | 40 | private: 41 | sc_signal irq_tieoff[NUM_DBG_IRQ]; 42 | }; 43 | -------------------------------------------------------------------------------- /demo-dma.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * A DMA device for demo purposes. 3 | * 4 | * Copyright (c) 2013 Xilinx Inc. 5 | * Written by Edgar E. Iglesias 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #define SC_INCLUDE_DYNAMIC_PROCESSES 27 | 28 | #include 29 | 30 | #include "tlm_utils/simple_initiator_socket.h" 31 | #include "tlm_utils/simple_target_socket.h" 32 | 33 | using namespace sc_core; 34 | using namespace std; 35 | 36 | #include "demo-dma.h" 37 | #include 38 | 39 | demodma::demodma(sc_module_name name) 40 | : sc_module(name), tgt_socket("tgt-socket") 41 | { 42 | tgt_socket.register_b_transport(this, &demodma::b_transport); 43 | memset(®s, 0, sizeof regs); 44 | 45 | SC_THREAD(do_dma_copy); 46 | dont_initialize(); 47 | sensitive << ev_dma_copy; 48 | } 49 | 50 | void demodma::do_dma_trans(tlm::tlm_command cmd, unsigned char *buf, 51 | sc_dt::uint64 addr, sc_dt::uint64 len) 52 | { 53 | tlm::tlm_generic_payload tr; 54 | sc_time delay = SC_ZERO_TIME; 55 | 56 | tr.set_command(cmd); 57 | tr.set_address(addr); 58 | tr.set_data_ptr(buf); 59 | tr.set_data_length(len); 60 | tr.set_streaming_width(len); 61 | tr.set_dmi_allowed(false); 62 | tr.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); 63 | 64 | if (regs.byte_en) { 65 | tr.set_byte_enable_ptr((unsigned char *) ®s.byte_en); 66 | tr.set_byte_enable_length(sizeof regs.byte_en); 67 | } 68 | 69 | init_socket->b_transport(tr, delay); 70 | 71 | switch (tr.get_response_status()) { 72 | case tlm::TLM_OK_RESPONSE: 73 | regs.error_resp = DEMODMA_RESP_OKAY; 74 | break; 75 | case tlm::TLM_ADDRESS_ERROR_RESPONSE: 76 | printf("%s:%d DMA transaction error!\n", __func__, __LINE__); 77 | regs.error_resp = DEMODMA_RESP_ADDR_DECODE_ERROR; 78 | break; 79 | default: 80 | printf("%s:%d DMA transaction error!\n", __func__, __LINE__); 81 | regs.error_resp = DEMODMA_RESP_BUS_GENERIC_ERROR; 82 | break; 83 | } 84 | } 85 | 86 | void demodma::update_irqs(void) 87 | { 88 | irq.write(regs.ctrl & DEMODMA_CTRL_DONE); 89 | } 90 | 91 | void demodma::do_dma_copy(void) 92 | { 93 | unsigned char buf[32]; 94 | 95 | while (true) { 96 | if (!(regs.ctrl & DEMODMA_CTRL_RUN)) { 97 | wait(ev_dma_copy); 98 | } 99 | 100 | if (regs.len > 0 && regs.ctrl & DEMODMA_CTRL_RUN) { 101 | unsigned int tlen = regs.len > sizeof buf ? sizeof buf : regs.len; 102 | 103 | do_dma_trans(tlm::TLM_READ_COMMAND, buf, regs.src_addr, tlen); 104 | do_dma_trans(tlm::TLM_WRITE_COMMAND, buf, regs.dst_addr, tlen); 105 | 106 | regs.dst_addr += tlen; 107 | regs.src_addr += tlen; 108 | regs.len -= tlen; 109 | } 110 | 111 | if (regs.len == 0 && regs.ctrl & DEMODMA_CTRL_RUN) { 112 | regs.ctrl &= ~DEMODMA_CTRL_RUN; 113 | /* If the DMA was running, signal done. */ 114 | regs.ctrl |= DEMODMA_CTRL_DONE; 115 | } else { 116 | // Artificial delay between bursts. 117 | wait(sc_time(1, SC_US)); 118 | } 119 | update_irqs(); 120 | } 121 | } 122 | 123 | void demodma::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) 124 | { 125 | tlm::tlm_command cmd = trans.get_command(); 126 | sc_dt::uint64 addr = trans.get_address(); 127 | unsigned char *data = trans.get_data_ptr(); 128 | unsigned int len = trans.get_data_length(); 129 | unsigned char *byt = trans.get_byte_enable_ptr(); 130 | unsigned int wid = trans.get_streaming_width(); 131 | 132 | if (byt != 0) { 133 | trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); 134 | return; 135 | } 136 | 137 | if (len > 4 || wid < len) { 138 | trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); 139 | return; 140 | } 141 | 142 | addr >>= 2; 143 | addr &= 7; 144 | if (trans.get_command() == tlm::TLM_READ_COMMAND) { 145 | memcpy(data, ®s.u32[addr], len); 146 | } else if (cmd == tlm::TLM_WRITE_COMMAND) { 147 | unsigned char buf[4]; 148 | memcpy(®s.u32[addr], data, len); 149 | switch (addr) { 150 | case 3: 151 | // speculative read for testing inline path. 152 | do_dma_trans(tlm::TLM_READ_COMMAND, buf, regs.src_addr, 4); 153 | /* The dma copies after a usec. */ 154 | ev_dma_copy.notify(delay + sc_time(1, SC_US)); 155 | break; 156 | default: 157 | /* No side-effect. */ 158 | break; 159 | } 160 | } 161 | trans.set_response_status(tlm::TLM_OK_RESPONSE); 162 | } 163 | -------------------------------------------------------------------------------- /demo-dma.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Xilinx Inc. 3 | * Written by Edgar E. Iglesias. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | enum { 25 | DEMODMA_CTRL_RUN = 1 << 0, 26 | DEMODMA_CTRL_DONE = 1 << 1, 27 | }; 28 | 29 | enum { 30 | DEMODMA_RESP_OKAY = 0, 31 | DEMODMA_RESP_BUS_GENERIC_ERROR = 1, 32 | DEMODMA_RESP_ADDR_DECODE_ERROR = 2, 33 | }; 34 | 35 | class demodma 36 | : public sc_core::sc_module 37 | { 38 | public: 39 | tlm_utils::simple_initiator_socket init_socket; 40 | tlm_utils::simple_target_socket tgt_socket; 41 | 42 | sc_out irq; 43 | demodma(sc_core::sc_module_name name); 44 | SC_HAS_PROCESS(demodma); 45 | private: 46 | union { 47 | struct { 48 | uint32_t dst_addr; 49 | uint32_t src_addr; 50 | uint32_t len; 51 | uint32_t ctrl; 52 | uint32_t byte_en; 53 | uint32_t error_resp; 54 | }; 55 | uint32_t u32[8]; 56 | } regs; 57 | 58 | sc_event ev_dma_copy; 59 | void do_dma_trans(tlm::tlm_command cmd, unsigned char *buf, 60 | sc_dt::uint64 addr, sc_dt::uint64 len); 61 | void do_dma_copy(void); 62 | void update_irqs(void); 63 | 64 | virtual void b_transport(tlm::tlm_generic_payload& trans, 65 | sc_time& delay); 66 | }; 67 | -------------------------------------------------------------------------------- /docs/lmac-demos.md: -------------------------------------------------------------------------------- 1 | # LMAC Demos 2 | 3 | The LMAC demos where developed in the DARPA POSH program in a collaboration 4 | between Xilinx Inc and LeWiz Inc. 5 | 6 | To reproduce the demos a large amount of software and RTL need to be built. 7 | This guide is not exhaustive but it will help you through building the main 8 | simulation components and provide pointers for some of the SW components that 9 | are a bit out of scope from this cosim github project. 10 | 11 | ## QEMU & HW-DTBs 12 | 13 | ### Build QEMU 14 | You'll have to use Xilinx QEMU that includes the Remote-Port modules for 15 | co-simulation. 16 | 17 | ``` 18 | git clone https://github.com/Xilinx/qemu.git 19 | mkdir build-qemu 20 | cd build-qemu 21 | ../qemu/configure --target-list=aarch64-softmmu,microblazeel-softmmu,riscv64-softmmu 22 | make 23 | ``` 24 | 25 | The binaries we'll be using in these examples can be found in the following 26 | paths: 27 | ``` 28 | build-qemu/riscv64-softmmu/qemu-system-riscv64 29 | build-qemu/aarch64-softmmu/qemu-system-aarch64 30 | ``` 31 | 32 | More details on the build process can be found here: 33 | https://github.com/Xilinx/qemu/blob/master/README.rst 34 | 35 | ### Build QEMU HW-DTBs 36 | 37 | Some of the Xilinx QEMU machine models (e.g ZCU102) are described using device-tree 38 | files. These device-tree's are fed to QEMU so that it can instantiate the emulated 39 | board. We refer to these device-trees as the HW device-trees or HW-DTB. 40 | 41 | Here's howto install the HW DTBs into ${HOME}/dts/: 42 | ``` 43 | git clone https://github.com/Xilinx/qemu-devicetrees.git 44 | cd qemu-devicetrees 45 | make OUTDIR=~/dts/ 46 | ``` 47 | 48 | ## systemctlm-cosim-demo 49 | 50 | This repo contains the SystemC/TLM source code for the co-simulation setup. 51 | It also submodules the LeWiz github repos with the LMAC RTL. 52 | 53 | This repo has dependencies to the SystemC libraries and to verilator. 54 | On a modern Ubuntu system, you can do the following: 55 | ``` 56 | apt-get install libsystemc-dev verilator 57 | ``` 58 | 59 | If your distro doesn't have packages for SystemC and verilator you may 60 | need to build them from source. 61 | 62 | Look here for more info: 63 | https://github.com/Xilinx/systemctlm-cosim-demo/blob/master/README 64 | 65 | Once the dependencies are build and installed, you can do: 66 | 67 | ``` 68 | git clone https://github.com/Xilinx/systemctlm-cosim-demo.git 69 | cd systemctlm-cosim-demo 70 | git submodule update --init 71 | echo HAVE_VERILOG_VERILATOR=y >>.config.mk 72 | make 73 | ``` 74 | 75 | When done, you should have the following lmac binaries built: 76 | 77 | ``` 78 | riscv_virt_lmac2_demo 79 | riscv_virt_lmac3_demo 80 | zynqmp_lmac2_demo 81 | ``` 82 | 83 | ## RISCV64 84 | 85 | ### RISCV64 SW Stack 86 | To run the RISCV64 demo, you'll need to build a RISCV64 SW stack. 87 | The Linux kernel will have to include the LMAC drivers developed in the posh program. 88 | 89 | This guide will guide you through the steps on howto build the RISCV64 SW stack 90 | and howto test it on QEMU: 91 | https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html 92 | 93 | When building the Linux kernel, you should use the posh-lmac branch in the following 94 | git repo instead: 95 | https://github.com/edgarigl/linux/tree/posh-lmac 96 | 97 | You'll need riscv64 compilers: 98 | ```apt-get install gcc-riscv64-linux-gnu``` 99 | 100 | Start with a default config: 101 | ```make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig``` 102 | 103 | Then follow-up with enabling what ever you need, including the LeWiz LMAC2 driver (CONFIG_LEWIZ_LMAC2): 104 | ```make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- menuconfig``` 105 | 106 | Build: 107 | ```make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu-``` 108 | 109 | ### Add LMAC to virt dtb 110 | 111 | When running the QEMU RISCV64 virt machine, QEMU will on-the-fly auto-generate a dtb file 112 | for the Guest Linux. We need to use a modified version of this dtb with the LMAC nodes. 113 | 114 | First we'll run QEMU and have it dump the generated dtb file. 115 | We'll need to copy the QEMU command-line from the run examples below 116 | and remove the ```-dtb virt.dtb``` option and append the ``-machine dumpdtb=virt.dtb`` 117 | option to make QEMU dump the DTB. 118 | 119 | Example: 120 | ``` 121 | qemu-system-riscv64 -M virt-cosim -smp 4 -serial stdio -display none -m 2G \ 122 | -bios opensbi-riscv64-virt-fw_jump.bin -kernel Image \ 123 | -append "root=/dev/vda ro console=ttyS0" \ 124 | -drive file=rootfs.ext2,format=raw,id=hd0 \ 125 | -device virtio-blk-device,drive=hd0 \ 126 | -object rng-random,filename=/dev/urandom,id=rng0 \ 127 | -device virtio-rng-device,rng=rng0 \ 128 | -device virtio-net-device,netdev=usernet -netdev user,id=usernet \ 129 | -machine dumpdtb=virt.dtb 130 | ``` 131 | 132 | Now, we'll disassemble it back to source: 133 | ``` 134 | dtc -I dtb -O dts -o virt.dts virt.dtb 135 | ``` 136 | 137 | And then we'll edit it adding the following at the end, inside of the soc node: 138 | ``` 139 | lmac2@0x280030000 { 140 | compatible = "lewiz,lmac2"; 141 | reg = < 0x00 0x28030000 0x00 0x10000 >; 142 | mac-address = [ 00 40 8c 00 00 01 ]; 143 | interrupt-names = "tx\0rx"; 144 | interrupt-parent = < 0x09 >; 145 | interrupts = < 0x32 0x34 >; 146 | }; 147 | ``` 148 | 149 | Convert it back to dtb: 150 | ``` 151 | dtc -I dts -O dtb -o virt.dtb virt.dts 152 | ``` 153 | 154 | ### Running 155 | 156 | Once you have a system going it's time to try the co-simulation. 157 | You'll need two terminals, one for QEMU and another for the SystemC simulators. 158 | 159 | QEMU: 160 | ``` 161 | mkdir /tmp/machine-riscv64/ 162 | qemu-system-riscv64 -M virt-cosim -smp 4 -serial stdio -display none -m 2G \ 163 | -dtb virt.dtb -bios opensbi-riscv64-virt-fw_jump.bin -kernel Image \ 164 | -append "root=/dev/vda ro console=ttyS0" \ 165 | -drive file=rootfs.ext2,format=raw,id=hd0 \ 166 | -device virtio-blk-device,drive=hd0 \ 167 | -object rng-random,filename=/dev/urandom,id=rng0 \ 168 | -device virtio-rng-device,rng=rng0 \ 169 | -device virtio-net-device,netdev=usernet -netdev user,id=usernet \ 170 | -netdev user,id=net4 \ 171 | -device remote-port-net,rp-adaptor0=/machine/cosim,rp-chan0=256,rp-chan1=266,netdev=net4 \ 172 | -machine-path /tmp/machine-riscv64 173 | ``` 174 | 175 | SystemC: 176 | ``` 177 | riscv_virt_lmac2_demo unix:/tmp/machine-riscv64/qemu-rport-_machine_cosim 10000 178 | ``` 179 | 180 | When Linux boots, you should now see the kernel discovering the co-simulated LMAC: 181 | ``` 182 | lmac2 28030000.lmac2: Lewiz at 0x28030000 mapped to 0xFFFFFFFF44020000, tx-irq=9 rx-irq=11 183 | ``` 184 | -------------------------------------------------------------------------------- /docs/zynq-7000-getting-started-guide.md: -------------------------------------------------------------------------------- 1 | # Setting up and Running a Co-Simulation with a System Clock Example 2 | 3 | This demonstration shows how to compile and run the Co-Simulation demo of 4 | Buildroot in QEMU with a simulated device in SystemC. **Buildroot was 5 | selected for this demo, but other Linux Kernel's can be built and deployed 6 | in QEMU and used as well.** This configuration is tested working for 7 | Ubuntu 18.0.4 and assumes that a `cosim` directory is created in your home 8 | directory. This walkthrough also assumes that the device being emulated by 9 | QEMU is the Xilinx Zynq-7000 SoC. This SoC seemed like a good candidate 10 | but the concept can apply to any QEMU machine which plugs in a compatible 11 | remoteport bus interface. 12 | 13 | Here is a basic diagram of the enviornment we will setup: 14 | ``` 15 | System Clock Demo 16 | +--------------------+ 17 | | SystemC-TLM | 18 | +--------+ | | 19 | | | Remote Port | Memory Mapped Regs | 20 | | QEMU |<--------------->+-------+------------+ 21 | | | | CLK | 0X4000000 | 22 | +--------+ +-------+------------+ 23 | | ... | ... | 24 | +-------+------------+ 25 | ``` 26 | 27 | ## Dependencies 28 | 29 | Below are the dependencies needed to compile all the libraries in this 30 | demo: 31 | 32 | ```bash 33 | sudo apt update 34 | sudo apt install git cmake make wget gcc g++ python3 pkg-config libglib2.0-dev libpixman-1-dev verilator expect cpio unzip rsync bc libssl-dev 35 | ``` 36 | 37 | ## Setup and Compilation 38 | 39 | Run these commands to clone and build the necessary repos (`~/cosim` 40 | assumed as the base directory). 41 | 42 | ### Create the base directory 43 | 44 | ```bash 45 | mkdir ~/cosim 46 | ``` 47 | 48 | ### SystemC Setup 49 | 50 | ```bash 51 | # Build and install the binaries 52 | cd ~/cosim 53 | wget https://www.accellera.org/images/downloads/standards/systemc/systemc-2.3.3.tar.gz 54 | tar xf systemc-2.3.3.tar.gz 55 | cd systemc-2.3.3/ 56 | CXXFLAGS=-std=c++11 ./configure --prefix=${HOME}/cosim/ 57 | make 58 | make install 59 | ``` 60 | 61 | ### QEMU Setup 62 | 63 | ```bash 64 | cd ~/cosim 65 | git clone https://github.com/Xilinx/qemu.git 66 | cd qemu 67 | git checkout 74d70f8008 68 | 69 | # Configure and build 70 | ./configure --target-list="arm-softmmu,aarch64-softmmu,microblazeel-softmmu,riscv32-softmmu,riscv64-softmmu,x86_64-softmmu" --enable-fdt --disable-kvm --disable-xen 71 | make -j$((`nproc`+1)) 72 | make install DESTDIR=${HOME}/cosim/ 73 | ``` 74 | 75 | ### Demo Setup 76 | 77 | ```bash 78 | # Clone the repo and the submodules 79 | cd ~/cosim 80 | git clone https://github.com/Xilinx/systemctlm-cosim-demo.git 81 | cd systemctlm-cosim-demo 82 | git submodule update --init libsystemctlm-soc 83 | 84 | # Create the Makefile configeration 85 | cat << EOF | tee .config.mk 86 | CXXFLAGS=-std=c++11 87 | SYSTEMC=${HOME}/cosim/ 88 | HAVE_VERILOG=n 89 | HAVE_VERILOG_VERILATOR=y 90 | HAVE_VERILOG_VCS=y 91 | VM_TRACE=1 92 | EOF 93 | 94 | # Build the demo 95 | make zynq_demo 96 | ``` 97 | 98 | ### Buildroot Setup 99 | 100 | ```bash 101 | cd ~/cosim 102 | git clone https://github.com/buildroot/buildroot.git 103 | cd buildroot 104 | git checkout 36edacce9c2c3b90f9bb11 105 | mkdir handles 106 | ``` 107 | 108 | For this walkthrough we will be configuring the demo to emulate the 109 | Zynq-7000 SoC. 110 | 111 | ```bash 112 | # Pull the .dtsi files for the Zynq-7000 113 | wget https://raw.githubusercontent.com/Xilinx/qemu-devicetrees/master/zynq-pl-remoteport.dtsi 114 | wget https://raw.githubusercontent.com/Xilinx/linux-xlnx/master/arch/arm/boot/dts/xilinx/zynq-7000.dtsi 115 | # kernel 5.4.75 zynq-zc702.dts 116 | wget https://raw.githubusercontent.com/torvalds/linux/6e97ed6efa701db070da0054b055c085895aba86/arch/arm/boot/dts/zynq-zc702.dts 117 | # Include zynq-pl-remoteport.dtsi in zynq-zc702.dts 118 | echo "#include \"zynq-pl-remoteport.dtsi\"" >> zynq-zc702.dts 119 | # Fetch xilinx_zynq_defconfig 120 | wget https://raw.githubusercontent.com/Xilinx/linux-xlnx/3fbb3a6c57a43342a7daec3bbae2f595c50bc969/arch/arm/configs/xilinx_zynq_defconfig 121 | 122 | # Setup the Buildroot compilation configeration 123 | rm .config .config.old -f 124 | cat << EOF | tee ".config" 125 | BR2_arm=y 126 | BR2_cortex_a9=y 127 | BR2_ARM_ENABLE_NEON=y 128 | BR2_ARM_ENABLE_VFP=y 129 | BR2_TOOLCHAIN_EXTERNAL=y 130 | BR2_TOOLCHAIN_EXTERNAL_BOOTLIN=y 131 | BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_ARMV7_EABIHF_GLIBC_STABLE=y 132 | BR2_TARGET_GENERIC_GETTY_PORT="ttyPS0" 133 | BR2_LINUX_KERNEL=y 134 | BR2_LINUX_KERNEL_CUSTOM_VERSION=y 135 | BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="5.4.75" 136 | BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y 137 | BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="xilinx_zynq_defconfig" 138 | BR2_LINUX_KERNEL_UIMAGE=y 139 | BR2_LINUX_KERNEL_UIMAGE_LOADADDR="0x8000" 140 | BR2_LINUX_KERNEL_DTS_SUPPORT=y 141 | BR2_LINUX_KERNEL_CUSTOM_DTS_PATH="zynq-7000.dtsi zynq-zc702.dts zynq-pl-remoteport.dtsi" 142 | BR2_TARGET_ROOTFS_CPIO=y 143 | BR2_TARGET_ROOTFS_CPIO_GZIP=y 144 | BR2_TARGET_ROOTFS_EXT2=y 145 | #BR2_TARGET_ROOTFS_TAR is not set 146 | EOF 147 | 148 | # Build 149 | make clean && make olddefconfig 150 | ./utils/brmake 151 | ``` 152 | 153 | ## Running the Demo 154 | 155 | In order to run the co-simulation demo, you will need two shells open. One 156 | for QEMU and the other for SystemC. In the first shell run the command 157 | below to start the SystemC simulation: 158 | 159 | ```bash 160 | LD_LIBRARY_PATH=${HOME}/cosim/lib-linux64/ ~/cosim/systemctlm-cosim-demo/zynq_demo unix:${HOME}/cosim/buildroot/handles/qemu-rport-_cosim@0 1000000 161 | ``` 162 | 163 | Start the QEMU instance in the second shell by running (in any directory): 164 | 165 | ```bash 166 | ${HOME}/cosim/usr/local/bin/qemu-system-aarch64 -M arm-generic-fdt-7series -m 1G -kernel ${HOME}/cosim/buildroot/output/images/uImage -dtb ${HOME}/cosim/buildroot/output/images/zynq-zc702.dtb --initrd ${HOME}/cosim/buildroot/output/images/rootfs.cpio.gz -serial /dev/null -serial mon:stdio -display none -net nic -net nic -net user -machine-path ${HOME}/cosim/buildroot/handles -icount 0,sleep=off -rtc clock=vm -sync-quantum 1000000 167 | ``` 168 | 169 | ## Example Output 170 | 171 | Below is some example output showing the Buildroot instance querying the 172 | SystemC simulated environment. **This demo shows how the system clock 173 | changes after each read from the memory address. The clock's memory 174 | address is 0x40000000. The value returned is the value of the system clock 175 | at that period of time**.: 176 | 177 | ```bash 178 | Welcome to Buildroot 179 | buildroot login: root 180 | # devmem 0x40000000 181 | 0x87AB9927 182 | #devmem 0x400000000 183 | 0x8BFF63F0 184 | # devmem 0x40000000 185 | 0x8F1F7EC3 186 | # devmem 0x40000000 187 | 0x917A5800 188 | # uname -a 189 | Linux buildroot 5.4.75-g7441ac1188d7-dirty #3 SMP Tue Apr 13 08:00:50 CST 2021 armv71 GNU/Linux 190 | #cat /proc/cpuinfo 191 | processor : 0 192 | model name : ARMv7 Processor rev 0 (v71) 193 | BogoMIPS : 2164.32 194 | Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 195 | CPU inplementer : 0x41 196 | CPU architecture: 7 197 | CPU variant :0x0 198 | CPU part :0xc09 199 | CPU revision : 0 200 | 201 | processor : 1 202 | model name : ARMv7 Processor rev 0 (v71) 203 | BogoMIPS : 2118.45 204 | Features :half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 205 | CPU implementer : 0x41 206 | CPU architecture: 7 207 | CPU variant : 0x0 208 | CPU part : 0xc09 209 | CPU revision : 0 210 | 211 | Hardware : Xilinx Zynq Platform 212 | Revision : 0000 213 | Serial : 0000000000000000 214 | ``` 215 | -------------------------------------------------------------------------------- /files-lmac2.mk: -------------------------------------------------------------------------------- 1 | # 2 | # systemctlm-cosim-demo Makefile fragment listing all LMAC2 verilog files. 3 | # 4 | # Copyright (c) 2019 Xilinx Inc. 5 | # Written by Edgar E. Iglesias 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | LM_CORE += $(LM2_DIR)/AXIS_LMAC_TOP/AXIS_LMAC_TOP.v 26 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/AXIS_BRIDGE_TOP.v 27 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/axis2fib_txctrl.v 28 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/axis2fib_rxctrl.v 29 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/fib2fmac_txctrl.v 30 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/fmac2fib_rxctrl.v 31 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/txdata_fifo256x64.v 32 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/rxdata_fifo256x64.v 33 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/rxrbcnt_fifo4x32.v 34 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/txwbcnt_fifo4x32.v 35 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/LMAC_CORE_TOP.v 36 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/RIF_IF_BRIDGE.v 37 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/rxrregif_fifo4x32.v 38 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/rxrregif_fifo4x8.v 39 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/txwregif_fifo4x16.v 40 | LM_CORE += $(LM2_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/txwregif_fifo4x8.v 41 | 42 | LM_CORE += $(LM2_DIR)/ASYNCH_FIFO/asynch_fifo.v 43 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/br_sfifo4x32.v 44 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/bsh32_dn_88.v 45 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/bsh8_dn_64.v 46 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/byte_reordering.v 47 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/crc32_d16s.v 48 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/crc32_d24s.v 49 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/crc32_d64.v 50 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/crc32_d8s.v 51 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/ctrl_2G_5G.v 52 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/eth_crc32_gen.v 53 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/fmac_fifo4Kx64.v 54 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/fmac_fifo4Kx8.v 55 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/fmac_fifo512x64_2clk.v 56 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/fmac_register_if_LE2.v 57 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/g2x_ctrl.v 58 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/gige_crc32x64.v 59 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/gigerx_bcnt_fifo256x16.v 60 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/gigerx_fifo256x64_2clk.v 61 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/gigerx_fifo256x8.v 62 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/gige_s2p.v 63 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/gige_tx_encap.v 64 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/gige_tx_gmii.v 65 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/rx_5G.v 66 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/rx_decap_LE2.v 67 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/rx_xgmii_LE2.v 68 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/tcore_fmac_core_LE2.v 69 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/tx_10G_wrap.v 70 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/tx_1G_wrap.v 71 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/tx_encap.v 72 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/txfifo_1024x64.v 73 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/tx_mac10g_crc32x64.v 74 | LM_CORE += $(LM2_DIR)/LMAC_CORE_TOP/tx_xgmii_LE2.v 75 | -------------------------------------------------------------------------------- /files-lmac3.mk: -------------------------------------------------------------------------------- 1 | # 2 | # systemctlm-cosim-demo Makefile fragment listing all LMAC2 verilog files. 3 | # 4 | # Copyright (c) 2019 Xilinx Inc. 5 | # Written by Edgar E. Iglesias 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | LM3_CORE += $(LM3_DIR)/AXIS_LMAC_TOP/AXIS_LMAC_TOP.v 26 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/AXIS_BRIDGE_TOP.v 27 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/axis2fib_txctrl.v 28 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/axis2fib_rxctrl.v 29 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/fib2fmac_txctrl.v 30 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/fmac2fib_rxctrl.v 31 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/txdata_fifo1024x256.v 32 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/rxdata_fifo1024x256.v 33 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/rxrbcnt_fifo256x64.v 34 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/txwbcnt_fifo256x64.v 35 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/LMAC_CORE_TOP.v 36 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/RIF_IF_BRIDGE.v 37 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/rxrregif_fifo4x32.v 38 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/rxrregif_fifo4x8.v 39 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/txwregif_fifo4x16.v 40 | LM3_CORE += $(LM3_DIR)/AXIS_BRIDGE/REG_IF_BRIDGE/txwregif_fifo4x8.v 41 | 42 | LM3_CORE += $(LM3_DIR)/ASYNCH_FIFO/asynch_fifo.v 43 | 44 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/LMAC_CORE_TOP.v 45 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/br_pre_ctrl_fifo1024x40.v 46 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/br_pre_data_fifo1024x256.v 47 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/br_sfifo4x32.v 48 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/byte_reordering.v 49 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/byte_reordering_wrap.v 50 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/eth_crc32_gen.v 51 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/fmac_fifo4Kx32.v 52 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/fmac_ipcs_fifo512x64.v 53 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/fmac_register_if_LE2.v 54 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/fmac_rx_fifo4Kx256.v 55 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/rx_100g.v 56 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/rx_50G.v 57 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/rx_cgmii_LE2.v 58 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/rx_decap_LE2.v 59 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/s2p10.v 60 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tcore_fmac_core_LE2.v 61 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tx_100G_wrap.v 62 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tx_10G_wrap.v 63 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tx_cgmii_LE2.v 64 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tx_encap_100G.v 65 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tx_encap_10G.v 66 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tx_mac10g_crc32x64.v 67 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/tx_xgmii_LE2.v 68 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/txfifo_1024x256.v 69 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/x2c_bcnt_fifo256x32.v 70 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/x2c_ctrl.v 71 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/x2c_ctrl_fifo1024x32.v 72 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/x2c_data_fifo1024x256.v 73 | 74 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D104.v 75 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D112.v 76 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D120.v 77 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D128.v 78 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D136.v 79 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D144.v 80 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D152.v 81 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D16.v 82 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D160.v 83 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D168.v 84 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D176.v 85 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D184.v 86 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D192.v 87 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D200.v 88 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D208.v 89 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D216.v 90 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D224.v 91 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D232.v 92 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D24.v 93 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D240.v 94 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D248.v 95 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D256.v 96 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D32.v 97 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D40.v 98 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D48.v 99 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D56.v 100 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D64.v 101 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D72.v 102 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D8.v 103 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D80.v 104 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D88.v 105 | LM3_CORE += $(LM3_DIR)/LMAC_CORE_TOP/CRCs/CRC32_D96.v 106 | -------------------------------------------------------------------------------- /iconnect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple TLM model of an interconnect 3 | * 4 | * Copyright (c) 2011 Edgar E. Iglesias. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /* Remove this local copy once we've moved the IP-XACT packages into 26 | * libsystemctlm-soc. 27 | */ 28 | #include "soc/interconnect/iconnect.h" 29 | -------------------------------------------------------------------------------- /lmac3_wrapper_top.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Xilinx Inc. 3 | // Written by Edgar E. Iglesias. 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library release; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | `timescale 1ns / 1ps 20 | 21 | module vlmac( 22 | clk, 23 | rst_n, 24 | 25 | xgmii_rxd, 26 | xgmii_rxc, 27 | 28 | xgmii_txd, 29 | xgmii_txc, 30 | 31 | tx_axis_mac_tdata, 32 | tx_axis_mac_tvalid, 33 | tx_axis_mac_tlast, 34 | tx_axis_mac_tuser, 35 | tx_axis_mac_tstrb, 36 | tx_axis_mac_tready, 37 | 38 | rx_axis_mac_tdata, 39 | rx_axis_mac_tvalid, 40 | rx_axis_mac_tlast, 41 | rx_axis_mac_tuser, 42 | rx_axis_mac_tstrb, 43 | rx_axis_mac_tready, 44 | 45 | host_addr_reg, 46 | reg_rd_start, 47 | reg_rd_done_out, 48 | FMAC_REGDOUT 49 | ); 50 | 51 | input wire clk; 52 | input wire rst_n; 53 | 54 | input wire [63:0] xgmii_rxd; 55 | input wire [7:0] xgmii_rxc; 56 | output wire [63:0] xgmii_txd; 57 | output wire [7:0] xgmii_txc; 58 | 59 | input wire [255:0] tx_axis_mac_tdata; 60 | input wire tx_axis_mac_tvalid; 61 | input wire tx_axis_mac_tlast; 62 | input wire tx_axis_mac_tuser; 63 | input wire [31:0] tx_axis_mac_tstrb; 64 | output wire tx_axis_mac_tready; 65 | 66 | output wire [255:0] rx_axis_mac_tdata; 67 | output wire rx_axis_mac_tvalid; 68 | output wire rx_axis_mac_tlast; 69 | output wire rx_axis_mac_tuser; 70 | output wire [31:0] rx_axis_mac_tstrb; 71 | input wire rx_axis_mac_tready; 72 | 73 | input wire [15:0] host_addr_reg; 74 | input reg_rd_start; 75 | output reg_rd_done_out; 76 | output [31:0] FMAC_REGDOUT; 77 | 78 | wire linkup; 79 | 80 | //--------- ADDED 8jan2020 81 | wire [255:0] xgmii_txd256; 82 | wire [31:0] xgmii_txc32; 83 | assign xgmii_txd = xgmii_txd256[63:0]; 84 | assign xgmii_txc = xgmii_txc32[7:0]; 85 | 86 | AXIS_LMAC_TOP mac( 87 | .clk(clk), 88 | .xA_clk(clk), 89 | .reset_(rst_n), 90 | 91 | .gen_en_wr(1'b0), 92 | .fmac_speed(3'b0), 93 | 94 | .tx_mac_aclk(clk), 95 | .tx_axis_mac_tdata(tx_axis_mac_tdata), 96 | .tx_axis_mac_tvalid(tx_axis_mac_tvalid), 97 | .tx_axis_mac_tlast(tx_axis_mac_tlast), 98 | .tx_axis_mac_tuser(tx_axis_mac_tuser), 99 | .tx_axis_mac_tstrb(tx_axis_mac_tstrb), 100 | .tx_axis_mac_tready(tx_axis_mac_tready), 101 | 102 | .tx_ifg_delay(tx_ifg_delay), 103 | .tx_collision(tx_collision), 104 | .tx_retransmit(tx_retransmit), 105 | .tx_statistics_vector(tx_statistics_vector), 106 | .tx_statistics_valid(tx_statistics_valid), 107 | 108 | .rx_mac_aclk(clk), 109 | .rx_axis_mac_tdata(rx_axis_mac_tdata), 110 | .rx_axis_mac_tvalid(rx_axis_mac_tvalid), 111 | .rx_axis_mac_tlast(rx_axis_mac_tlast), 112 | .rx_axis_mac_tuser(rx_axis_mac_tuser), 113 | .rx_axis_mac_tstrb(rx_axis_mac_tstrb), 114 | .rx_axis_mac_tready(rx_axis_mac_tready), 115 | 116 | .rx_axis_filter_tuser(rx_axis_mac_filter_tuser), 117 | .rx_axis_compatible_mode(1'b1), 118 | .rx_statistics_vector(rx_statistics_vector), 119 | .rx_statistics_valid(rx_statistics_valid), 120 | 121 | .TCORE_MODE(1'b0), 122 | 123 | .cgmii_txd(xgmii_txd256), 124 | .cgmii_txc(xgmii_txc32), 125 | .cgmii_rxd(xgmii_rxd[63:0]), 126 | .cgmii_rxc(xgmii_rxc[7:0]), 127 | 128 | .host_addr_reg(host_addr_reg), 129 | .SYS_ADDR(4'b0), 130 | 131 | .fail_over(fail_over), 132 | .fmac_ctrl(32'h00000808), 133 | .fmac_ctrl1(32'h000005ee), 134 | .fmac_rxd_en(1'b1), 135 | 136 | .mac_pause_value(32'b0), 137 | .mac_addr0(48'h408c000001), 138 | 139 | .reg_rd_start(reg_rd_start), 140 | .reg_rd_done_out(reg_rd_done_out), 141 | .FMAC_REGDOUT(FMAC_REGDOUT) 142 | ); 143 | endmodule 144 | -------------------------------------------------------------------------------- /lmac_wrapper_top.v: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Xilinx Inc. 3 | // Written by Edgar E. Iglesias. 4 | // 5 | // This library is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU Lesser General Public 7 | // License as published by the Free Software Foundation; either 8 | // version 2.1 of the License, or (at your option) any later version. 9 | // 10 | // This library is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | // Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public 16 | // License along with this library release; if not, write to the Free Software 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | `timescale 1ns / 1ps 20 | 21 | module vlmac( 22 | clk, 23 | rst_n, 24 | 25 | xgmii_rxd, 26 | xgmii_rxc, 27 | 28 | xgmii_txd, 29 | xgmii_txc, 30 | 31 | tx_axis_mac_tdata, 32 | tx_axis_mac_tvalid, 33 | tx_axis_mac_tlast, 34 | tx_axis_mac_tuser, 35 | tx_axis_mac_tstrb, 36 | tx_axis_mac_tready, 37 | 38 | rx_axis_mac_tdata, 39 | rx_axis_mac_tvalid, 40 | rx_axis_mac_tlast, 41 | rx_axis_mac_tuser, 42 | rx_axis_mac_tstrb, 43 | rx_axis_mac_tready, 44 | 45 | host_addr_reg, 46 | reg_rd_start, 47 | reg_rd_done_out, 48 | FMAC_REGDOUT 49 | ); 50 | 51 | input wire clk; 52 | input wire rst_n; 53 | 54 | input wire [63:0] xgmii_rxd; 55 | input wire [7:0] xgmii_rxc; 56 | output wire [63:0] xgmii_txd; 57 | output wire [7:0] xgmii_txc; 58 | 59 | input wire [63:0] tx_axis_mac_tdata; 60 | input wire tx_axis_mac_tvalid; 61 | input wire tx_axis_mac_tlast; 62 | input wire tx_axis_mac_tuser; 63 | input wire [7:0] tx_axis_mac_tstrb; 64 | output wire tx_axis_mac_tready; 65 | 66 | output wire [63:0] rx_axis_mac_tdata; 67 | output wire rx_axis_mac_tvalid; 68 | output wire rx_axis_mac_tlast; 69 | output wire rx_axis_mac_tuser; 70 | output wire [7:0] rx_axis_mac_tstrb; 71 | input wire rx_axis_mac_tready; 72 | 73 | input wire [15:0] host_addr_reg; 74 | input reg_rd_start; 75 | output reg_rd_done_out; 76 | output [31:0] FMAC_REGDOUT; 77 | 78 | wire linkup; 79 | AXIS_LMAC_TOP mac( 80 | .clk(clk), 81 | .xA_clk(clk), 82 | .reset_(rst_n), 83 | 84 | .gen_en_wr(1'b0), 85 | .fmac_speed(3'b0), 86 | 87 | .tx_mac_aclk(clk), 88 | .tx_axis_mac_tdata(tx_axis_mac_tdata), 89 | .tx_axis_mac_tvalid(tx_axis_mac_tvalid), 90 | .tx_axis_mac_tlast(tx_axis_mac_tlast), 91 | .tx_axis_mac_tuser(tx_axis_mac_tuser), 92 | .tx_axis_mac_tstrb(tx_axis_mac_tstrb), 93 | .tx_axis_mac_tready(tx_axis_mac_tready), 94 | 95 | .tx_ifg_delay(tx_ifg_delay), 96 | .tx_collision(tx_collision), 97 | .tx_retransmit(tx_retransmit), 98 | .tx_statistics_vector(tx_statistics_vector), 99 | .tx_statistics_valid(tx_statistics_valid), 100 | 101 | .rx_mac_aclk(clk), 102 | .rx_axis_mac_tdata(rx_axis_mac_tdata), 103 | .rx_axis_mac_tvalid(rx_axis_mac_tvalid), 104 | .rx_axis_mac_tlast(rx_axis_mac_tlast), 105 | .rx_axis_mac_tuser(rx_axis_mac_tuser), 106 | .rx_axis_mac_tstrb(rx_axis_mac_tstrb), 107 | .rx_axis_mac_tready(rx_axis_mac_tready), 108 | 109 | .rx_axis_filter_tuser(rx_axis_mac_filter_tuser), 110 | .rx_axis_compatible_mode(1'b1), 111 | .rx_statistics_vector(rx_statistics_vector), 112 | .rx_statistics_valid(rx_statistics_valid), 113 | 114 | .TCORE_MODE(1'b0), 115 | 116 | .xgmii_txd(xgmii_txd), 117 | .xgmii_txc(xgmii_txc), 118 | .xgmii_rxd(xgmii_rxd), 119 | .xgmii_rxc(xgmii_rxc), 120 | 121 | 122 | .host_addr_reg(host_addr_reg), 123 | .SYS_ADDR(4'b0), 124 | 125 | .fail_over(fail_over), 126 | .fmac_ctrl(32'h00000808), 127 | .fmac_ctrl1(32'h000005ee), 128 | .fmac_rxd_en(1'b1), 129 | 130 | .mac_pause_value(32'b0), 131 | .mac_addr0(48'h408c000001), 132 | 133 | .reg_rd_start(reg_rd_start), 134 | .reg_rd_done_out(reg_rd_done_out), 135 | .FMAC_REGDOUT(FMAC_REGDOUT) 136 | ); 137 | endmodule 138 | -------------------------------------------------------------------------------- /packages/ipxact/xilinx.com/demos/zynqmp_lmac2_demo/1.0/zynqmp_lmac2_demo.1.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 24 | 25 | xilinx.com 26 | demos 27 | zynqmp_lmac2_demo 28 | 1.0 29 | 30 | 31 | 32 | hierarchical 33 | zynqmp_lmac2_demo.designcfg_1.0 34 | 35 | 36 | 37 | 38 | zynqmp_lmac2_demo.designcfg_1.0 39 | 40 | 41 | 42 | 43 | 44 | clk 45 | 46 | in 47 | 48 | 49 | bool 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | rst 59 | 60 | in 61 | 62 | 63 | bool 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | clockPeriod 76 | 10 77 | 78 | 79 | clockPort 80 | clk 81 | 82 | 83 | clockPulseDuration 84 | 5 85 | 86 | 87 | clockTimeUnit 88 | us 89 | 90 | 91 | resetPort 92 | rst 93 | 94 | 95 | singleShotDuration 96 | 1 97 | 98 | 99 | singleShotOffset 100 | 0 101 | 102 | 103 | singleShotTimeUnit 104 | us 105 | 106 | 107 | singleShotValue 108 | 1 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /packages/ipxact/xilinx.com/demos/zynqmp_lmac2_demo/1.0/zynqmp_lmac2_demo.designcfg.1.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 24 | 25 | xilinx.com 26 | demos 27 | zynqmp_lmac2_demo.designcfg 28 | 1.0 29 | 30 | 31 | xilinx_zynqmp_0 32 | 33 | 34 | 35 | iconnect_0 36 | 37 | 38 | 39 | axidma_mm2s_0 40 | 41 | 42 | 43 | axidma_s2mm_0 44 | 45 | 46 | 47 | tlm2axis_bridge_0 48 | 49 | 50 | 51 | axis2tlm_bridge_0 52 | 53 | 54 | 55 | tlm2apb_bridge_0 56 | 57 | 58 | 59 | lmac_wrapper_top_0 60 | 61 | 62 | 63 | signal_inverter_0 64 | 65 | 66 | 67 | tlm_xgmii_phy_0 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /packages/ipxact/xilinx.com/systemctlm-cosim-demo/axidma_mm2s/1.0/axidma_mm2s.1.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 24 | 25 | xilinx.com 26 | systemctlm-cosim-demo 27 | axidma_mm2s 28 | 1.0 29 | 30 | 31 | init_target 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | tlmgp 40 | 41 | 42 | init_socket 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | tgt_target 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | tlmgp 60 | 61 | 62 | tgt_socket 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | stream_target 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | tlmgp 80 | 81 | 82 | stream_socket 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | SystemC 95 | sc_implementation 96 | 97 | 98 | 99 | 100 | sc_implementation 101 | SystemC 102 | axidma_mm2s 103 | 104 | sc_fileset 105 | 106 | 107 | 108 | 109 | 110 | init_socket 111 | 112 | provides 113 | 114 | 115 | 116 | tgt_socket 117 | 118 | provides 119 | 120 | 121 | 122 | stream_socket 123 | 124 | provides 125 | 126 | 127 | 128 | irq 129 | 130 | out 131 | 132 | 133 | bool 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | sc_fileset 146 | 147 | ../../../../../../xilinx-axidma.h 148 | systemCSource 149 | true 150 | 151 | 152 | ../../../../../../xilinx-axidma.cc 153 | systemCSource 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /packages/ipxact/xilinx.com/systemctlm-cosim-demo/axidma_s2mm/1.0/axidma_s2mm.1.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 24 | 25 | xilinx.com 26 | systemctlm-cosim-demo 27 | axidma_s2mm 28 | 1.0 29 | 30 | 31 | init_target 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | tlmgp 40 | 41 | 42 | init_socket 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | tgt_target 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | tlmgp 60 | 61 | 62 | tgt_socket 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | stream_target 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | tlmgp 80 | 81 | 82 | stream_socket 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | SystemC 95 | sc_implementation 96 | 97 | 98 | 99 | 100 | sc_implementation 101 | SystemC 102 | axidma_s2mm 103 | 104 | sc_fileset 105 | 106 | 107 | 108 | 109 | 110 | init_socket 111 | 112 | provides 113 | 114 | 115 | 116 | tgt_socket 117 | 118 | provides 119 | 120 | 121 | 122 | stream_socket 123 | 124 | provides 125 | 126 | 127 | 128 | irq 129 | 130 | out 131 | 132 | 133 | bool 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | sc_fileset 146 | 147 | ../../../../../../xilinx-axidma.h 148 | systemCSource 149 | true 150 | 151 | 152 | ../../../../../../xilinx-axidma.cc 153 | systemCSource 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /packages/ipxact/xilinx.com/systemctlm-cosim-demo/tlm_xgmii_phy/1.0/tlm_xgmii_phy.1.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 24 | 25 | xilinx.com 26 | systemctlm-cosim-demo 27 | tlm_xgmii_phy 28 | 1.0 29 | 30 | 31 | tlm_init 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | tlmgp 40 | 41 | 42 | init_socket 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | xgmii_master 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | xxd 60 | 61 | 62 | xxd_out 63 | 64 | 65 | 66 | 67 | xxc 68 | 69 | 70 | xxc_out 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | tlm_target 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | tlmgp 88 | 89 | 90 | tgt_socket 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | xgmii_slave 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | xxd 110 | 111 | 112 | xxd_in 113 | 114 | 115 | 116 | 117 | xxc 118 | 119 | 120 | xxc_in 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | SystemC 135 | sc_implementation 136 | sc_design 137 | 138 | 139 | 140 | 141 | sc_implementation 142 | SystemC 143 | 144 | sc_fileset 145 | 146 | 147 | 148 | sc_design 149 | 150 | 151 | 152 | 153 | 154 | clk 155 | 156 | in 157 | 158 | 159 | bool 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | init_socket 169 | 170 | provides 171 | 172 | 173 | 174 | xxd_in 175 | 176 | in 177 | 178 | 179 | sc_bv 180 | 181 | 182 | 183 | 184 | 64-1 185 | 0 186 | 187 | 188 | 189 | 190 | 191 | xxd_out 192 | 193 | out 194 | 195 | 196 | sc_bv 197 | 198 | 199 | 200 | 201 | 64-1 202 | 0 203 | 204 | 205 | 206 | 207 | 208 | tgt_socket 209 | 210 | provides 211 | 212 | 213 | 214 | xxc_out 215 | 216 | out 217 | 218 | 219 | sc_bv 220 | 221 | 222 | 223 | 224 | 8-1 225 | 0 226 | 227 | 228 | 229 | 230 | 231 | xxc_in 232 | 233 | in 234 | 235 | 236 | sc_bv 237 | 238 | 239 | 240 | 241 | 8-1 242 | 0 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | sc_fileset 252 | 253 | ../../../../../../tlm-xgmii-phy.h 254 | systemCSource 255 | true 256 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /packages/ipxact/xilinx.com/systemctlm-cosim-demo/tlm_xgmii_phy/1.0/tlm_xgmii_phy.design.1.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 24 | 25 | xilinx.com 26 | systemctlm-cosim-demo 27 | tlm_xgmii_phy.design 28 | 1.0 29 | 30 | 31 | tx 32 | 33 | 34 | {c8d281c0-ad5e-4bfe-a5fc-f3f137a7757f} 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | rx 47 | 48 | 49 | {41ce6089-8e03-4dbe-8c36-06d8ab355fd1} 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | rx_tlm_target_to_tlm_target 64 | 65 | 66 | 67 | 68 | tx_xgmii_slave_to_xgmii_slave 69 | 70 | 71 | 72 | 73 | rx_xgmii_master_to_xgmii_master 74 | 75 | 76 | 77 | 78 | tx_tlm_init_to_tlm_init 79 | 80 | 81 | 82 | 83 | 84 | 85 | rx_clk_to_clk 86 | 87 | 88 | 89 | 90 | 91 | 92 | tx_clk_to_clk 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | tlm_target 140 | 141 | 142 | 143 | 144 | xgmii_master 145 | 146 | 147 | 148 | 149 | tlm_init 150 | 151 | 152 | 153 | 154 | xgmii_slave 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /packages/ipxact/xilinx.com/systemctlm-cosim-demo/tlm_xgmii_phy/1.0/tlm_xgmii_phy.designcfg.1.0.xml: -------------------------------------------------------------------------------- 1 | 2 | 24 | 25 | xilinx.com 26 | systemctlm-cosim-demo 27 | tlm_xgmii_phy.designcfg 28 | 1.0 29 | 30 | 31 | tx 32 | 33 | 34 | 35 | rx 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /pcie-ats-demo/pcie-acc-md5sum-vfio.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * This VFIO demo application calculates MD5 checksums on files using the 3 | * pcie-ats-demo. 4 | * 5 | * Copyright (c) 2021 Xilinx Inc. 6 | * Written by Francisco Iglesias 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #define SC_INCLUDE_DYNAMIC_PROCESSES 31 | 32 | #include "systemc" 33 | using namespace sc_core; 34 | using namespace sc_dt; 35 | using namespace std; 36 | 37 | #include "tlm.h" 38 | #include "tlm_utils/simple_initiator_socket.h" 39 | #include "tlm_utils/simple_target_socket.h" 40 | 41 | #include "tlm-modules/tlm-splitter.h" 42 | #include "tlm-bridges/tlm2vfio-bridge.h" 43 | 44 | #define SZ_4K (4 * 1024) 45 | #define SZ_32K (32 * 1024) 46 | 47 | // Top simulation module. 48 | SC_MODULE(Top) 49 | { 50 | vfio_dev vdev; 51 | 52 | SC_HAS_PROCESS(Top); 53 | 54 | enum { 55 | R_CTRL = 0x0, 56 | R_ADDR_LSB = 0x4, 57 | R_LENGTH = 0x8, 58 | R_VAL = 0xC, 59 | R_STATUS = 0x10, 60 | R_ADDR_MSB = 0x14, 61 | R_MD5_RESULT_0 = 0x18, 62 | R_MD5_RESULT_1 = 0x1C, 63 | R_MD5_RESULT_2 = 0x20, 64 | R_MD5_RESULT_3 = 0x24, 65 | 66 | R_CTRL_TRANSLATE = 1 << 0, 67 | R_CTRL_READ = 1 << 1, 68 | R_CTRL_WRITE = 1 << 2, 69 | R_CTRL_MD5SUM = 1 << 3, 70 | 71 | R_STATUS_DONE = 1 << 0, 72 | R_STATUS_ERR = 1 << 1, 73 | }; 74 | 75 | Top(sc_module_name name, const char *devname, int iommu_group, 76 | const char *filename) : 77 | sc_module(name), 78 | vdev(devname, iommu_group), 79 | m_filename(filename) 80 | { 81 | SC_THREAD(run_md5); 82 | } 83 | 84 | // 85 | // Compute the MD5 message digest on input file 86 | // 87 | void run_md5() 88 | { 89 | uintptr_t map_uint; 90 | uint64_t map_size; 91 | uint8_t *tmp; 92 | struct stat s; 93 | void *mbuf; 94 | int fd; 95 | 96 | cout << endl << " * MD5: " << m_filename << endl; 97 | 98 | // 99 | // Open the file and get file stats 100 | // 101 | fd = open(m_filename, O_RDWR); 102 | if (fd < 0) { 103 | perror("open"); 104 | exit(EXIT_FAILURE); 105 | } 106 | if (fstat(fd, &s) < 0) { 107 | perror("fstat"); 108 | goto err1; 109 | } 110 | 111 | // 112 | // Calculate map_size 113 | // 114 | map_size = (s.st_size / SZ_4K) * SZ_4K; 115 | if (s.st_size % SZ_4K) { 116 | map_size += SZ_4K; 117 | } 118 | 119 | // 120 | // mmap the file 121 | // 122 | mbuf = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 123 | if (mbuf == MAP_FAILED) { 124 | perror("mmap"); 125 | goto err1; 126 | } 127 | 128 | // 129 | // Lock pages to allow direct DMA. 130 | // 131 | mlock(mbuf, map_size); 132 | 133 | // 134 | // VFIO map. 135 | // 136 | tmp = (uint8_t *) mbuf; 137 | map_uint = (uintptr_t) tmp; 138 | vdev.iommu_map_dma(map_uint, SZ_32K, map_size, 139 | VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE); 140 | 141 | // 142 | // MD5 configuration & computation 143 | // 144 | write32(R_ADDR_MSB, 0); 145 | write32(R_ADDR_LSB, SZ_32K); 146 | write32(R_LENGTH, s.st_size); 147 | 148 | write32(R_STATUS, 0); 149 | write32(R_CTRL, R_CTRL_MD5SUM); 150 | wait_for_done(); 151 | 152 | // 153 | // MD5 result 154 | // 155 | cout << " - MD5 result: "; 156 | for (uint32_t addr = R_MD5_RESULT_0; 157 | addr <= R_MD5_RESULT_3; addr +=4) { 158 | uint32_t r = read32(addr); 159 | 160 | cout << hex << right 161 | << setw(2) << setfill('0') 162 | << ((r >> 0) & 0xFF) 163 | << ((r >> 8) & 0xFF) 164 | << ((r >> 16) & 0xFF) 165 | << ((r >> 24) & 0xFF); 166 | } 167 | cout << endl; 168 | 169 | // 170 | // VFIO unmap. 171 | // 172 | vdev.iommu_unmap_dma((uintptr_t) SZ_32K, map_size, 173 | VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE); 174 | 175 | 176 | // 177 | // munmap. 178 | // 179 | if (munmap(mbuf, s.st_size) ) { 180 | perror("munmap"); 181 | } 182 | 183 | close(fd); 184 | 185 | sc_stop(); 186 | return; 187 | err1: 188 | close(fd); 189 | exit(EXIT_FAILURE); 190 | } 191 | 192 | void write32(uint32_t addr, uint32_t val) 193 | { 194 | // only using BAR0 195 | uint8_t *map = (uint8_t *) vdev.map[0]; 196 | 197 | memcpy_to_io(map + addr, reinterpret_cast(&val), sizeof(val)); 198 | } 199 | 200 | uint32_t read32(uint32_t addr) 201 | { 202 | // only using BAR0 203 | uint8_t *map = (uint8_t *) vdev.map[0]; 204 | uint32_t val; 205 | 206 | memcpy_from_io(reinterpret_cast(&val), 207 | map + addr, sizeof(val)); 208 | 209 | return val; 210 | } 211 | 212 | void wait_for_done() 213 | { 214 | uint32_t r; 215 | 216 | do { 217 | r = read32(R_STATUS); 218 | } while (r == 0); 219 | } 220 | 221 | const char *m_filename; 222 | }; 223 | 224 | int sc_main(int argc, char *argv[]) 225 | { 226 | int iommu_group; 227 | 228 | if (argc < 4) { 229 | printf("%s: device-name iommu-group filename\n", argv[0]); 230 | exit(EXIT_FAILURE); 231 | } 232 | 233 | iommu_group = strtoull(argv[2], NULL, 10); 234 | Top top("Top", argv[1], iommu_group, argv[3]); 235 | 236 | sc_start(); 237 | 238 | return 0; 239 | } 240 | -------------------------------------------------------------------------------- /pcie-ats-demo/pcie-ats-demo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Top level of PCIe ATS accelerator demo. 3 | * 4 | * Copyright (c) 2021 Xilinx Inc. 5 | * Written by Francisco Iglesias 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #define SC_INCLUDE_DYNAMIC_PROCESSES 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "systemc.h" 34 | #include "tlm_utils/simple_initiator_socket.h" 35 | #include "tlm_utils/simple_target_socket.h" 36 | #include "tlm_utils/tlm_quantumkeeper.h" 37 | 38 | using namespace sc_core; 39 | using namespace sc_dt; 40 | using namespace std; 41 | 42 | #include "trace.h" 43 | #include "iconnect.h" 44 | #include "debugdev.h" 45 | 46 | #include "remote-port-tlm.h" 47 | #include "remote-port-tlm-pci-ep.h" 48 | #include "pcie-acc.h" 49 | 50 | #ifdef HAVE_VERILOG_VERILATOR 51 | #include "verilated.h" 52 | #endif 53 | 54 | SC_MODULE(Top) 55 | { 56 | public: 57 | SC_HAS_PROCESS(Top); 58 | 59 | remoteport_tlm_pci_ep rp_pci_ep; 60 | pcie_acc acc; 61 | sc_signal rst; 62 | 63 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 64 | sc_module(name), 65 | rp_pci_ep("rp-pci-ep", 0, NR_MMIO_BAR, NR_IRQ, sk_descr), 66 | acc("pci-acc"), 67 | rst("rst") 68 | { 69 | m_qk.set_global_quantum(quantum); 70 | 71 | rp_pci_ep.rst(rst); 72 | rp_pci_ep.bind(acc); 73 | 74 | acc.rst(rst); 75 | 76 | SC_THREAD(pull_reset); 77 | } 78 | 79 | void pull_reset(void) { 80 | /* Pull the reset signal. */ 81 | rst.write(true); 82 | wait(1, SC_US); 83 | rst.write(false); 84 | } 85 | 86 | private: 87 | tlm_utils::tlm_quantumkeeper m_qk; 88 | }; 89 | 90 | void usage(void) 91 | { 92 | cout << "tlm socket-path sync-quantum-ns" << endl; 93 | } 94 | 95 | int sc_main(int argc, char* argv[]) 96 | { 97 | Top *top; 98 | uint64_t sync_quantum; 99 | sc_trace_file *trace_fp = NULL; 100 | 101 | #if HAVE_VERILOG_VERILATOR 102 | Verilated::commandArgs(argc, argv); 103 | #endif 104 | 105 | if (argc < 3) { 106 | sync_quantum = 10000; 107 | } else { 108 | sync_quantum = strtoull(argv[2], NULL, 10); 109 | } 110 | 111 | sc_set_time_resolution(1, SC_PS); 112 | 113 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 114 | 115 | if (argc < 3) { 116 | sc_start(1, SC_PS); 117 | sc_stop(); 118 | usage(); 119 | exit(EXIT_FAILURE); 120 | } 121 | 122 | trace_fp = sc_create_vcd_trace_file("trace"); 123 | if (trace_fp) { 124 | trace(trace_fp, *top, top->name()); 125 | } 126 | 127 | sc_start(); 128 | if (trace_fp) { 129 | sc_close_vcd_trace_file(trace_fp); 130 | } 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /pcie-ats-demo/pcie-ats-demo.md: -------------------------------------------------------------------------------- 1 | # Launching the pcie-ats-demo 2 | 3 | ## Overview 4 | 5 | This demo shows an x86 host co-simulating with an attached PCIe MD5 accelerator. 6 | The x86 host is emulated by QEMU and the PCIe End-point is modelled in 7 | SystemC. 8 | 9 | The PCIe MD5 accelerator contains an Address Translation Cache (ATC) and will 10 | issue PCIe Address Translation Service (ATS) requests towards the x86 host 11 | in order to get hold of the Virtual to Physical Adresses translations in 12 | the hosts IOMMU. This allows the MD5 accelerator to later issue memory 13 | transactions using already translated addresses. 14 | 15 | Instructions for how to run an Ubuntu based guest system with Xilinx QEMU 16 | together with the pcie-ats-demo demo are found below. 17 | 18 | ## Building the pcie-ats-demo 19 | 20 | The pcie-ats-demo also depends on the libssl-dev Ubuntu/debian package (or 21 | equivalent package in case a different distribution is running on the host) 22 | besides the dependencies mentioned in the README found in the top directory. 23 | Below are instructions on how to install the package on a Ubuntu / debian 24 | system. 25 | 26 | ``` 27 | # Install libssl-dev 28 | $ sudo apt-get install libssl-dev 29 | ``` 30 | 31 | Once above package has been installed (and the README in the top directory has 32 | been followed regarding the SystemC installation and also configuration of the 33 | systemctlm-cosim-demo), one should be able to build the demo with the commands 34 | found below. 35 | 36 | ``` 37 | # Build the pcie-ats-demo 38 | $ cd /path/to/systemctlm-cosim-demo 39 | $ make pcie-ats-demo/pcie-ats-demo 40 | ``` 41 | 42 | ## Preparing the Ubuntu cloud image VM 43 | 44 | Download the the Ubuntu cloud image. 45 | 46 | ``` 47 | ~$ cd ~/Downloads/ 48 | ~$ wget https://cloud-images.ubuntu.com/releases/focal/release-20210125/ubuntu-20.04-server-cloudimg-amd64.img 49 | ~$ wget https://cloud-images.ubuntu.com/releases/focal/release-20210125/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic 50 | ~$ wget https://cloud-images.ubuntu.com/releases/focal/release-20210125/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic 51 | ``` 52 | 53 | Resize the image to 10G. 54 | 55 | ``` 56 | ~$ qemu-img resize ~/Downloads/ubuntu-20.04-server-cloudimg-amd64.img 10G 57 | ``` 58 | 59 | Create a disk image with user-data to be used for starting the cloud 60 | image. 61 | 62 | ``` 63 | ~$ sudo apt-get install cloud-image-utils 64 | ~$ cd ~/Downloads 65 | ~$ cat >user-data < .config.mk 134 | SYSTEMC = /opt/systemc-2.3.2/ 135 | EOF 136 | $ git submodule update --init libsystemctlm-soc 137 | $ make pcie-ats-demo/test-pcie-ats-demo-vfio pcie-ats-demo/pcie-acc-md5sum-vfio 138 | ``` 139 | 140 | ## Connecting QEMU and with the pcie-ats-demo 141 | 142 | Launch the pcie-ats-demo in another terminal: 143 | 144 | ``` 145 | $ ./pcie-ats-demo/pcie-ats-demo unix:/tmp/machine-x86/qemu-rport-_machine_peripheral_rp0_rp 10000 146 | ``` 147 | 148 | Press ctrl+a + c in QEMU's terminal to enter the monitor and instantiate a 149 | remote-port adaptor and also hotplug the PCIe EP: 150 | 151 | ``` 152 | device_add remote-port-pci-adaptor,bus=rootport1,id=rp0 153 | device_add remote-port-pci-device,bus=rootport,rp-adaptor0=rp,rp-chan0=0,vendor-id=0x10ee,device-id=0xd004,class-id=0x0700,revision=0x12,nr-io-bars=0,nr-mm-bars=1,bar-size0=0x100000,id=pcidev1,ats=true 154 | 155 | ``` 156 | 157 | More information about how to hotplug PCIe EPs into QEMU can be found inside 158 | the libsystemctlm-soc's documentation (see 159 | libsystemctlm-soc/docs/pcie-rtl-bridges/overview.md). 160 | 161 | ## Running VFIO demo applications 162 | 163 | After connecting the pcie-ats-demo EP with QEMU one can verify that 164 | the Ubuntu guest system and Linux kernel has found the device with the 165 | following command: 166 | 167 | ``` 168 | $ sudo lspci -v 169 | ... 170 | 01:00.0 Serial controller: Xilinx Corporation Device d004 (rev 12) (prog-if 01 [16450]) 171 | Subsystem: Red Hat, Inc. Device 1100 172 | Physical Slot: 0 173 | Flags: fast devsel, IRQ 23 174 | Memory at fe800000 (32-bit, non-prefetchable) [size=1M] 175 | Capabilities: [40] Express Endpoint, MSI 00 176 | Capabilities: [100] Address Translation Service (ATS) 177 | ... 178 | ``` 179 | 180 | For running the VFIO demo applications below commands can be used (more 181 | detailed information about the commands can be found inside libsystemctlm-soc). 182 | 183 | The following VFIO demo application will compute the MD5 digest for a given file, 184 | in this case the Makefile, using the PCIe MD5 accelerator. This can be compared 185 | with the results of the hosts md5sum application. 186 | 187 | ``` 188 | $ cd ~/github/systemctlm-cosim-demo/ 189 | $ sudo modprobe vfio-pci nointxmask=1 190 | $ sudo sh -c 'echo 10ee d004 > /sys/bus/pci/drivers/vfio-pci/new_id' 191 | $ # Find the iommu group 192 | $ ls -l /sys/bus/pci/devices/0000\:01\:00.0/iommu_group 193 | $ # The iommu group was 3, MD5 checksum will be calculated on the 'Makefile' 194 | $ sudo LD_LIBRARY_PATH=/opt/systemc-2.3.2/lib-linux64/ ./pcie-ats-demo/pcie-acc-md5sum-vfio 0000:01:00.0 3 Makefile 195 | 196 | SystemC 2.3.2-Accellera --- Mar 30 2021 14:55:02 197 | Copyright (c) 1996-2017 by all Contributors, 198 | ALL RIGHTS RESERVED 199 | Device supports 9 regions, 5 irqs 200 | mapped 0 at 0x7f21b9835000 201 | 202 | * MD5: Makefile 203 | - MD5 result: 605639aa8252d495f5273e1df83110aa 204 | 205 | Info: /OSCI/SystemC: Simulation stopped by user. 206 | ``` 207 | -------------------------------------------------------------------------------- /pcie-ats-demo/test-pcie-ats-demo-vfio.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Xilinx Inc. 3 | * Written by Francisco Iglesias 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #define SC_INCLUDE_DYNAMIC_PROCESSES 28 | 29 | #include "systemc" 30 | using namespace sc_core; 31 | using namespace sc_dt; 32 | using namespace std; 33 | 34 | #include "tlm.h" 35 | #include "tlm_utils/simple_initiator_socket.h" 36 | #include "tlm_utils/simple_target_socket.h" 37 | 38 | #include "tlm-modules/tlm-splitter.h" 39 | #include "tlm-bridges/tlm2vfio-bridge.h" 40 | 41 | #define SZ_4K (4 * 1024) 42 | #define SZ_32K (32 * 1024) 43 | 44 | // Top simulation module. 45 | SC_MODULE(Top) 46 | { 47 | vfio_dev vdev; 48 | 49 | SC_HAS_PROCESS(Top); 50 | 51 | enum { 52 | R_CTRL = 0x0, 53 | R_ADDR_LSB = 0x4, 54 | R_LENGTH = 0x8, 55 | R_VAL = 0xC, 56 | R_STATUS = 0x10, 57 | R_ADDR_MSB = 0x14, 58 | R_MD5_RESULT_0 = 0x18, 59 | R_MD5_RESULT_1 = 0x1C, 60 | R_MD5_RESULT_2 = 0x20, 61 | R_MD5_RESULT_3 = 0x24, 62 | 63 | R_CTRL_TRANSLATE = 1 << 0, 64 | R_CTRL_READ = 1 << 1, 65 | R_CTRL_WRITE = 1 << 2, 66 | R_CTRL_MD5SUM = 1 << 3, 67 | 68 | R_STATUS_DONE = 1 << 0, 69 | R_STATUS_ERR = 1 << 1, 70 | }; 71 | 72 | Top(sc_module_name name, const char *devname, int iommu_group, 73 | const char *filename) : 74 | sc_module(name), 75 | vdev(devname, iommu_group), 76 | m_map(0), 77 | m_map_size(SZ_32K), 78 | m_filename(filename) 79 | { 80 | map_mem(); 81 | 82 | SC_THREAD(run_tests); 83 | } 84 | 85 | ~Top() 86 | { 87 | vdev.iommu_unmap_dma((uintptr_t) 0, m_map_size, 88 | VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE); 89 | munmap(m_map, m_map_size); 90 | } 91 | 92 | void map_mem() 93 | { 94 | int flags = MAP_SHARED | MAP_ANONYMOUS; 95 | uintptr_t map_uint; 96 | void *m; 97 | 98 | m = mmap(0, m_map_size, PROT_READ | PROT_WRITE, flags, 0, 0); 99 | if (m == MAP_FAILED) { 100 | perror("tlm_mm_vfio"); 101 | SC_REPORT_ERROR("tlm_mm_vfio", "mmap failure"); 102 | } 103 | 104 | // Lock pages to allow direct DMA. 105 | mlock(m, m_map_size * 2); 106 | 107 | m_map = (uint8_t *) m; 108 | map_uint = (uintptr_t) m_map; 109 | 110 | vdev.iommu_map_dma(map_uint, 0, m_map_size, 111 | VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE); 112 | } 113 | 114 | void wait_for_done() 115 | { 116 | uint32_t r; 117 | 118 | do { 119 | r = read32(R_STATUS); 120 | } while (r == 0); 121 | } 122 | 123 | void test_ATC_load() 124 | { 125 | cout << " * " << __func__ 126 | << ", translate addr: 0x0" 127 | << ", length: 32 K" << endl; 128 | 129 | write32(R_ADDR_MSB, 0); 130 | write32(R_ADDR_LSB, 0); 131 | write32(R_LENGTH, SZ_32K); 132 | write32(R_STATUS, 0); 133 | write32(R_CTRL, R_CTRL_TRANSLATE); 134 | wait_for_done(); 135 | } 136 | 137 | void test_read() 138 | { 139 | uint32_t addr; 140 | 141 | for (addr = 0; addr < SZ_32K; addr += 256) { 142 | cout << " * Test read from addr: 0x" 143 | << hex << addr << endl; 144 | 145 | m_map[addr + 0] = 0xAA; 146 | m_map[addr + 1] = 0xBB; 147 | m_map[addr + 2] = 0xCC; 148 | m_map[addr + 3] = 0xDD; 149 | 150 | write32(R_ADDR_MSB, 0); 151 | write32(R_ADDR_LSB, addr); 152 | write32(R_LENGTH, 4); 153 | 154 | write32(R_STATUS, 0); 155 | write32(R_CTRL, R_CTRL_READ); 156 | wait_for_done(); 157 | 158 | cout << " - Read data: 0x" << hex 159 | << read32(R_VAL) << endl; 160 | } 161 | } 162 | 163 | void test_write() 164 | { 165 | uint32_t addr; 166 | 167 | for (addr = 0; addr < SZ_32K; addr += 256) { 168 | cout << " * Test write to addr: 0x" 169 | << hex << addr << " with data: 0x" 170 | << addr << endl;; 171 | 172 | write32(R_ADDR_MSB, 0); 173 | write32(R_ADDR_LSB, addr); 174 | write32(R_LENGTH, 4); 175 | 176 | write32(R_STATUS, 0); 177 | write32(R_VAL, addr); 178 | write32(R_CTRL, R_CTRL_WRITE); 179 | wait_for_done(); 180 | 181 | cout << " - data at addr: 0x" << hex << addr << ", data: 0x" 182 | << reinterpret_cast(&m_map[addr])[0] 183 | << endl; 184 | } 185 | } 186 | 187 | // 188 | // Compute the MD5 message digest on input file 189 | // 190 | void test_md5() 191 | { 192 | uintptr_t map_uint; 193 | uint64_t map_size; 194 | uint8_t *tmp; 195 | struct stat s; 196 | void *mbuf; 197 | int fd; 198 | 199 | cout << " * MD5: " << m_filename << endl; 200 | 201 | fd = open(m_filename, O_RDWR); 202 | if (fd < 0) { 203 | perror("open"); 204 | exit(EXIT_FAILURE); 205 | } 206 | if (fstat(fd, &s) < 0) { 207 | perror("fstat"); 208 | goto err1; 209 | } 210 | 211 | // 212 | // Calculate map_size 213 | // 214 | map_size = (s.st_size / SZ_4K) * SZ_4K; 215 | if (s.st_size % SZ_4K) { 216 | map_size += SZ_4K; 217 | } 218 | 219 | mbuf = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 220 | if (mbuf == MAP_FAILED) { 221 | perror("mmap"); 222 | goto err1; 223 | } 224 | 225 | // Lock pages to allow direct DMA. 226 | mlock(mbuf, map_size); 227 | 228 | // vfio map. 229 | tmp = (uint8_t *) mbuf; 230 | map_uint = (uintptr_t) tmp; 231 | vdev.iommu_map_dma(map_uint, SZ_32K, map_size, 232 | VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE); 233 | 234 | // MD5 235 | write32(R_ADDR_MSB, 0); 236 | write32(R_ADDR_LSB, SZ_32K); 237 | write32(R_LENGTH, s.st_size); 238 | 239 | write32(R_STATUS, 0); 240 | write32(R_CTRL, R_CTRL_MD5SUM); 241 | wait_for_done(); 242 | 243 | cout << " - MD5 result: "; 244 | for (uint32_t addr = R_MD5_RESULT_0; 245 | addr <= R_MD5_RESULT_3; addr +=4) { 246 | uint32_t r = read32(addr); 247 | 248 | cout << hex << right 249 | << setw(2) << setfill('0') 250 | << ((r >> 0) & 0xFF) 251 | << ((r >> 8) & 0xFF) 252 | << ((r >> 16) & 0xFF) 253 | << ((r >> 24) & 0xFF); 254 | } 255 | cout << endl; 256 | 257 | vdev.iommu_unmap_dma((uintptr_t) SZ_32K, map_size, 258 | VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE); 259 | 260 | if (munmap(mbuf, s.st_size) ) { 261 | perror("munmap"); 262 | } 263 | 264 | close(fd); 265 | 266 | sc_stop(); 267 | 268 | return; 269 | err1: 270 | close(fd); 271 | exit(EXIT_FAILURE); 272 | } 273 | 274 | void run_tests() 275 | { 276 | test_ATC_load(); 277 | test_read(); 278 | test_write(); 279 | test_md5(); 280 | } 281 | 282 | void write32(uint32_t addr, uint32_t val) 283 | { 284 | // only using BAR0 285 | uint8_t *map = (uint8_t *) vdev.map[0]; 286 | 287 | memcpy_to_io(map + addr, reinterpret_cast(&val), sizeof(val)); 288 | } 289 | 290 | uint32_t read32(uint32_t addr) 291 | { 292 | // only using BAR0 293 | uint8_t *map = (uint8_t *) vdev.map[0]; 294 | uint32_t val; 295 | 296 | memcpy_from_io(reinterpret_cast(&val), 297 | map + addr, sizeof(val)); 298 | 299 | return val; 300 | } 301 | 302 | uint8_t *m_map; 303 | uint64_t m_map_size; 304 | 305 | const char *m_filename; 306 | }; 307 | 308 | int sc_main(int argc, char *argv[]) 309 | { 310 | int iommu_group; 311 | 312 | if (argc < 4) { 313 | printf("%s: device-name iommu-group filename\n", argv[0]); 314 | exit(EXIT_FAILURE); 315 | } 316 | 317 | iommu_group = strtoull(argv[2], NULL, 10); 318 | Top top("Top", argv[1], iommu_group, argv[3]); 319 | 320 | sc_start(); 321 | 322 | return 0; 323 | } 324 | -------------------------------------------------------------------------------- /pcie/versal/cpm-qdma-demo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022, Advanced Micro Devices, Inc. 3 | * Written by Fred Konrad 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | #define SC_INCLUDE_DYNAMIC_PROCESSES 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "systemc.h" 32 | #include "tlm_utils/simple_initiator_socket.h" 33 | #include "tlm_utils/simple_target_socket.h" 34 | #include "tlm_utils/tlm_quantumkeeper.h" 35 | 36 | #include "tlm-modules/pcie-controller.h" 37 | #include "soc/pci/core/pcie-root-port.h" 38 | #include "soc/pci/xilinx/qdma.h" 39 | #include "memory.h" 40 | 41 | using namespace sc_core; 42 | using namespace sc_dt; 43 | using namespace std; 44 | 45 | #include "trace.h" 46 | #include "iconnect.h" 47 | #include "debugdev.h" 48 | 49 | #include "remote-port-tlm.h" 50 | #include "remote-port-tlm-pci-ep.h" 51 | 52 | #define PCI_VENDOR_ID_XILINX (0x10ee) 53 | #define PCI_DEVICE_ID_XILINX_EF100 (0xd004) 54 | #define PCI_SUBSYSTEM_ID_XILINX_TEST (0x000A) 55 | 56 | #define PCI_CLASS_BASE_NETWORK_CONTROLLER (0x02) 57 | 58 | #ifndef PCI_EXP_LNKCAP_ASPM_L0S 59 | #define PCI_EXP_LNKCAP_ASPM_L0S 0x00000400 /* ASPM L0s Support */ 60 | #endif 61 | 62 | #define KiB (1024) 63 | #define RAM_SIZE (4 * KiB) 64 | 65 | #define NR_MMIO_BAR 6 66 | #define NR_IRQ NR_QDMA_IRQ 67 | 68 | #ifdef QDMA_CPM4_VERSION 69 | #define QDMA_TYPE qdma_cpm4 70 | #else 71 | #define QDMA_TYPE qdma_cpm5 72 | #endif 73 | 74 | template 75 | class pcie_versal : public pci_device_base 76 | { 77 | private: 78 | QDMA_t qdma; 79 | 80 | // BARs towards the QDMA 81 | tlm_utils::simple_initiator_socket user_bar_init_socket; 82 | tlm_utils::simple_initiator_socket cfg_init_socket; 83 | 84 | // QDMA towards PCIe interface (host) 85 | tlm_utils::simple_target_socket brdg_dma_tgt_socket; 86 | 87 | // MSI-X propagation 88 | sc_vector > signals_irq; 89 | 90 | // 91 | // Nothing to attach to the QDMA yet, just add a dummy memory. 92 | // With that the testcase will be able to check what has been 93 | // written in the memory.. Add an interconnect, so we can map 94 | // it anywhere. 95 | // 96 | iconnect<1, 1> bus; 97 | memory sbi_dummy; 98 | 99 | void bar_b_transport(int bar_nr, tlm::tlm_generic_payload &trans, 100 | sc_time &delay) 101 | { 102 | switch (bar_nr) { 103 | case QDMA_USER_BAR_ID: 104 | user_bar_init_socket->b_transport(trans, delay); 105 | break; 106 | case 0: 107 | cfg_init_socket->b_transport(trans, delay); 108 | break; 109 | default: 110 | SC_REPORT_ERROR("pcie_versal", 111 | "writing to an unimplemented bar"); 112 | trans.set_response_status( 113 | tlm::TLM_GENERIC_ERROR_RESPONSE); 114 | break; 115 | } 116 | } 117 | 118 | // 119 | // Forward DMA requests received from the CPM5 QDMA 120 | // 121 | void fwd_dma_b_transport(tlm::tlm_generic_payload& trans, 122 | sc_time& delay) 123 | { 124 | dma->b_transport(trans, delay); 125 | } 126 | 127 | // 128 | // MSI-X propagation 129 | // 130 | void irq_thread(unsigned int i) 131 | { 132 | while (true) { 133 | wait(signals_irq[i].value_changed_event()); 134 | irq[i].write(signals_irq[i].read()); 135 | } 136 | } 137 | 138 | public: 139 | SC_HAS_PROCESS(pcie_versal); 140 | 141 | pcie_versal(sc_core::sc_module_name name) : 142 | 143 | pci_device_base(name, NR_MMIO_BAR, NR_IRQ), 144 | 145 | qdma("qdma"), 146 | 147 | user_bar_init_socket("user_bar_init_socket"), 148 | cfg_init_socket("cfg_init_socket"), 149 | brdg_dma_tgt_socket("brdg-dma-tgt-socket"), 150 | 151 | signals_irq("signals_irq", NR_IRQ), 152 | 153 | bus("bus"), 154 | sbi_dummy("sbi_dummy", sc_time(0, SC_NS), RAM_SIZE) 155 | { 156 | // 157 | // QDMA connections 158 | // 159 | user_bar_init_socket.bind(qdma.user_bar); 160 | cfg_init_socket.bind(qdma.config_bar); 161 | 162 | // Setup DMA forwarding path (qdma.dma -> upstream to host) 163 | qdma.dma.bind(brdg_dma_tgt_socket); 164 | brdg_dma_tgt_socket.register_b_transport( 165 | this, &pcie_versal::fwd_dma_b_transport); 166 | 167 | // Connect the SBI dummy RAM 168 | bus.memmap(0x102100000ULL, 0x1000 - 1, 169 | ADDRMODE_RELATIVE, -1, sbi_dummy.socket); 170 | qdma.card_bus.bind((*bus.t_sk[0])); 171 | 172 | // Setup MSI-X propagation 173 | for (unsigned int i = 0; i < NR_IRQ; i++) { 174 | qdma.irq[i](signals_irq[i]); 175 | sc_spawn(sc_bind(&pcie_versal::irq_thread, this, i)); 176 | } 177 | } 178 | 179 | void rst(sc_signal& rst) 180 | { 181 | qdma.rst(rst); 182 | } 183 | }; 184 | 185 | PhysFuncConfig getPhysFuncConfig() 186 | { 187 | PhysFuncConfig cfg; 188 | PMCapability pmCap; 189 | PCIExpressCapability pcieCap; 190 | MSIXCapability msixCap; 191 | uint32_t bar_flags = PCI_BASE_ADDRESS_MEM_TYPE_64; 192 | uint32_t msixTableSz = NR_IRQ; 193 | uint32_t tableOffset = 0x100 | 4; // Table offset: 0, BIR: 4 194 | uint32_t pba = 0x140000 | 4; // BIR: 4 195 | uint32_t maxLinkWidth; 196 | 197 | cfg.SetPCIVendorID(PCI_VENDOR_ID_XILINX); 198 | // QDMA 199 | cfg.SetPCIDeviceID(0x903F); 200 | 201 | cfg.SetPCIClassProgIF(0); 202 | cfg.SetPCIClassDevice(0); 203 | cfg.SetPCIClassBase(PCI_CLASS_BASE_NETWORK_CONTROLLER); 204 | 205 | cfg.SetPCIBAR0(256 * KiB, bar_flags); 206 | cfg.SetPCIBAR2(256 * KiB, bar_flags); 207 | cfg.SetPCIBAR4(256 * KiB, bar_flags); 208 | 209 | cfg.SetPCISubsystemVendorID(PCI_VENDOR_ID_XILINX); 210 | cfg.SetPCISubsystemID(PCI_SUBSYSTEM_ID_XILINX_TEST); 211 | cfg.SetPCIExpansionROMBAR(0, 0); 212 | 213 | cfg.AddPCICapability(pmCap); 214 | 215 | maxLinkWidth = 1 << 4; 216 | pcieCap.SetDeviceCapabilities(PCI_EXP_DEVCAP_RBER); 217 | pcieCap.SetLinkCapabilities(PCI_EXP_LNKCAP_SLS_2_5GB | maxLinkWidth 218 | | PCI_EXP_LNKCAP_ASPM_L0S); 219 | pcieCap.SetLinkStatus(PCI_EXP_LNKSTA_CLS_2_5GB | PCI_EXP_LNKSTA_NLW_X1); 220 | cfg.AddPCICapability(pcieCap); 221 | 222 | msixCap.SetMessageControl(msixTableSz-1); 223 | msixCap.SetTableOffsetBIR(tableOffset); 224 | msixCap.SetPendingBitArray(pba); 225 | cfg.AddPCICapability(msixCap); 226 | 227 | return cfg; 228 | } 229 | 230 | // Host / PCIe RC 231 | // 232 | // This pcie_host uses Remote-port to connect to a QEMU PCIe RC. 233 | // If you'd like to connect this demo to something else, you need 234 | // to replace this implementation with the host model you've got. 235 | // 236 | SC_MODULE(pcie_host) 237 | { 238 | private: 239 | remoteport_tlm_pci_ep rp_pci_ep; 240 | 241 | public: 242 | pcie_root_port rootport; 243 | sc_in rst; 244 | 245 | pcie_host(sc_module_name name, const char *sk_descr) : 246 | sc_module(name), 247 | rp_pci_ep("rp-pci-ep", 0, 1, 0, sk_descr), 248 | rootport("rootport"), 249 | rst("rst") 250 | { 251 | rp_pci_ep.rst(rst); 252 | rp_pci_ep.bind(rootport); 253 | } 254 | }; 255 | 256 | SC_MODULE(Top) 257 | { 258 | public: 259 | SC_HAS_PROCESS(Top); 260 | 261 | pcie_host host; 262 | 263 | PCIeController pcie_ctlr; 264 | pcie_versal qdma; 265 | 266 | // 267 | // Reset signal. 268 | // 269 | sc_signal rst; 270 | 271 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 272 | sc_module(name), 273 | host("host", sk_descr), 274 | pcie_ctlr("pcie-ctlr", getPhysFuncConfig()), 275 | qdma("pcie-qdma"), 276 | rst("rst") 277 | { 278 | m_qk.set_global_quantum(quantum); 279 | 280 | // Setup TLP sockets (host.rootport <-> pcie-ctlr) 281 | host.rootport.init_socket.bind(pcie_ctlr.tgt_socket); 282 | pcie_ctlr.init_socket.bind(host.rootport.tgt_socket); 283 | 284 | // 285 | // PCIeController <-> QDMA connections 286 | // 287 | pcie_ctlr.bind(qdma); 288 | 289 | // Reset signal 290 | host.rst(rst); 291 | qdma.rst(rst); 292 | 293 | SC_THREAD(pull_reset); 294 | } 295 | 296 | void pull_reset(void) { 297 | /* Pull the reset signal. */ 298 | rst.write(true); 299 | wait(1, SC_US); 300 | rst.write(false); 301 | } 302 | 303 | private: 304 | tlm_utils::tlm_quantumkeeper m_qk; 305 | }; 306 | 307 | void usage(void) 308 | { 309 | cout << "tlm socket-path sync-quantum-ns" << endl; 310 | } 311 | 312 | int sc_main(int argc, char* argv[]) 313 | { 314 | Top *top; 315 | uint64_t sync_quantum; 316 | sc_trace_file *trace_fp = NULL; 317 | 318 | if (argc < 3) { 319 | sync_quantum = 10000; 320 | } else { 321 | sync_quantum = strtoull(argv[2], NULL, 10); 322 | } 323 | 324 | sc_set_time_resolution(1, SC_PS); 325 | 326 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 327 | 328 | if (argc < 3) { 329 | sc_start(1, SC_PS); 330 | sc_stop(); 331 | usage(); 332 | exit(EXIT_FAILURE); 333 | } 334 | 335 | trace_fp = sc_create_vcd_trace_file("trace"); 336 | if (trace_fp) { 337 | trace(trace_fp, *top, top->name()); 338 | } 339 | 340 | sc_start(); 341 | if (trace_fp) { 342 | sc_close_vcd_trace_file(trace_fp); 343 | } 344 | return 0; 345 | } 346 | -------------------------------------------------------------------------------- /pcie/versal/cpm-qdma-demos.md: -------------------------------------------------------------------------------- 1 | # Running the cpm5-qdma-demo / cpm4-qdma-demo 2 | 3 | ## Overview 4 | 5 | These demos show an x86 host co-simulating with an attached PCIe endpoint 6 | containing a CPM5 QDMA subsystem model (cpm5-qdma-demo) or a CPM4 QDMA 7 | subsystem model (cpm4-qdma-demo). The x86 host is emulated by QEMU and the 8 | PCIe End-point is modelled in SystemC. 9 | 10 | Instructions for how to run an Ubuntu based guest system with Xilinx QEMU 11 | together with the cpm5-qdma-demo or cpm4-qdma-demo are found below. The 12 | instructions also demonstrate how to exercise the CPM5 (or CPM4) QDMA 13 | model with Xilinx open source QDMA driver and userspace applications from 14 | inside the Ubuntu guest system. 15 | 16 | ## Build SystemC 2.3.3 and Xilinx QEMU 17 | 18 | Follow the instructions on how to build Acelleras SystemC library and Xilinx 19 | QEMU found in the 20 | [zynq-7000-getting-started-guide](../../docs/zynq-7000-getting-started-guide.md#systemc-setup). 21 | 22 | ## Build the cpm5-qdma-demo and cpm4-qdma-demo 23 | 24 | Make sure to have installed required systemctlm-cosim-demo dependencies listed 25 | in the project [README](../../README). 26 | 27 | ``` 28 | $ sudo apt-get install linux-libc-dev 29 | ``` 30 | 31 | Download and build the cpm5-qdma-demo and cpm4-qdma-demo by following 32 | the following instructions. 33 | 34 | ``` 35 | $ git clone https://github.com/Xilinx/systemctlm-cosim-demo.git 36 | $ cd systemctlm-cosim-demo 37 | $ git submodule update --init libsystemctlm-soc 38 | $ git submodule update --init pcie-model 39 | # Change /path/to to the location where the SystemC library was installed 40 | $ cat < .config.mk 41 | SYSTEMC = /path/to/systemc-2.3.3/ 42 | EOF 43 | $ make pcie/versal/cpm5-qdma-demo pcie/versal/cpm4-qdma-demo 44 | ``` 45 | 46 | ## Preparing the Ubuntu cloud image VM 47 | 48 | Download the the Ubuntu cloud image. 49 | 50 | ``` 51 | ~$ cd ~/Downloads/ 52 | ~$ wget https://cloud-images.ubuntu.com/releases/focal/release-20210125/ubuntu-20.04-server-cloudimg-amd64.img 53 | ~$ wget https://cloud-images.ubuntu.com/releases/focal/release-20210125/unpacked/ubuntu-20.04-server-cloudimg-amd64-vmlinuz-generic 54 | ~$ wget https://cloud-images.ubuntu.com/releases/focal/release-20210125/unpacked/ubuntu-20.04-server-cloudimg-amd64-initrd-generic 55 | ``` 56 | 57 | Resize the image to 30G. 58 | 59 | ``` 60 | ~$ qemu-img resize ~/Downloads/ubuntu-20.04-server-cloudimg-amd64.img 30G 61 | ``` 62 | 63 | Create a disk image with user-data to be used for starting the cloud 64 | image. 65 | 66 | ``` 67 | ~$ sudo apt-get install cloud-image-utils 68 | ~$ cd ~/Downloads 69 | ~$ cat >user-data < /sys/bus/pci/devices/0000:02:00.0/qdma/qmax 185 | 186 | # Configure the first queue: Memory Mapped, Host to Card. 187 | $ ./bin/dma-ctl qdma02000 q add idx 0 mode mm dir h2c 188 | qdma02000-MM-0 H2C added. 189 | Added 1 Queues. 190 | 191 | # Start that queue. 192 | $ ./bin/dma-ctl qdma02000 q start idx 0 dir h2c aperture_sz 4096 193 | dma-ctl: Info: Default ring size set to 2048 194 | 1 Queues started, idx 0 ~ 0. 195 | ``` 196 | 197 | Exercise the CPM5 (or CPM4) QDMA model in the PCIe Endpoint and transfer 198 | memory (a fake PDI file) from the QEMU x86 host to the SBI keyhole 199 | aperture address by issueing below commands. In this demo a 4 KB memory 200 | has been connected a the SBI keyhole aperture address. 201 | ``` 202 | # Create a fake PDI of 1KB size. 203 | $ dd if=/dev/zero of=/home/ubuntu/test.pdi count=1 bs=1024 204 | # Copy a 1KB of a file from the host to the SBI. 205 | $ ./bin/dma-to-device -d /dev/qdma02000-MM-0 -f /home/ubuntu/test.pdi -s 1024 -a 0x102100000 206 | size=1024 Average BW = 31.673125 KB/sec 207 | ``` 208 | -------------------------------------------------------------------------------- /riscv_virt_lmac2_demo.cc: -------------------------------------------------------------------------------- 1 | #define BASE_ADDR 0x28000000ULL 2 | 3 | #include "zynqmp_lmac2_demo.cc" 4 | -------------------------------------------------------------------------------- /riscv_virt_lmac3_demo.cc: -------------------------------------------------------------------------------- 1 | #define BASE_ADDR 0x28000000ULL 2 | 3 | #include "zynqmp_lmac3_demo.cc" 4 | -------------------------------------------------------------------------------- /tlm-xgmii-phy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Partial model of a TLM XGMII PHY. 3 | * 4 | * Copyright (c) 2019 Xilinx Inc. 5 | * Written by Edgar E. Iglesias. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | #ifndef __TLM_XGMII_PHY_H__ 26 | #define __TLM_XGMII_PHY_H__ 27 | 28 | #define SC_INCLUDE_DYNAMIC_PROCESSES 29 | #include 30 | #include "tlm-bridges/tlm2xgmii-bridge.h" 31 | #include "tlm-bridges/xgmii2tlm-bridge.h" 32 | 33 | class tlm_xgmii_phy 34 | : public sc_core::sc_module 35 | { 36 | public: 37 | xgmii2tlm_bridge tx; 38 | tlm2xgmii_bridge rx; 39 | 40 | tlm_xgmii_phy(sc_core::sc_module_name name); 41 | 42 | private: 43 | }; 44 | 45 | tlm_xgmii_phy::tlm_xgmii_phy(sc_module_name name) 46 | : sc_module(name), 47 | tx("tx"), 48 | rx("rx") 49 | { 50 | } 51 | #endif 52 | -------------------------------------------------------------------------------- /tlm2apb-bridge.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Xilinx Inc. 3 | * Written by Edgar E. Iglesias. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | #define SC_INCLUDE_DYNAMIC_PROCESSES 25 | 26 | template 27 | class ADDR_TYPE, int ADDR_WIDTH, template class DATA_TYPE, int DATA_WIDTH> 28 | class tlm2apb_bridge 29 | : public sc_core::sc_module 30 | { 31 | public: 32 | tlm_utils::simple_target_socket tgt_socket; 33 | 34 | tlm2apb_bridge(sc_core::sc_module_name name); 35 | SC_HAS_PROCESS(tlm2apb_bridge); 36 | 37 | sc_in clk; 38 | sc_out psel; 39 | sc_out penable; 40 | sc_out pwrite; 41 | sc_out > paddr; 42 | sc_out > pwdata; 43 | sc_in > prdata; 44 | sc_in pready; 45 | 46 | private: 47 | virtual void b_transport(tlm::tlm_generic_payload& trans, 48 | sc_time& delay); 49 | }; 50 | 51 | template 52 | class ADDR_TYPE, int ADDR_WIDTH, template class DATA_TYPE, int DATA_WIDTH> 53 | tlm2apb_bridge ::tlm2apb_bridge(sc_module_name name) 54 | : sc_module(name), tgt_socket("tgt-socket"), 55 | clk("clk"), 56 | psel("psel"), 57 | penable("penable"), 58 | pwrite("pwrite"), 59 | paddr("paddr"), 60 | pwdata("pwdata"), 61 | prdata("prdata"), 62 | pready("pready") 63 | { 64 | tgt_socket.register_b_transport(this, &tlm2apb_bridge::b_transport); 65 | } 66 | 67 | template 68 | class ADDR_TYPE, int ADDR_WIDTH, template class DATA_TYPE, int DATA_WIDTH> 69 | void tlm2apb_bridge 70 | 71 | ::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) 72 | { 73 | tlm::tlm_command cmd = trans.get_command(); 74 | sc_dt::uint64 addr = trans.get_address(); 75 | unsigned char* data = trans.get_data_ptr(); 76 | unsigned int len = trans.get_data_length(); 77 | unsigned char* byt = trans.get_byte_enable_ptr(); 78 | unsigned int wid = trans.get_streaming_width(); 79 | uint32_t tprdata = 0; 80 | uint32_t tpwdata = 0; 81 | 82 | if (byt != 0) { 83 | trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); 84 | return; 85 | } 86 | 87 | if (len != 4 || wid < len) { 88 | trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); 89 | return; 90 | } 91 | 92 | /* FIXME: This truncation should be done somewhere else. */ 93 | addr >>= 2; 94 | 95 | /* Setup phase. Prepare all ctrl signals except enable. */ 96 | psel = BOOL_TYPE(1); 97 | paddr = addr; 98 | 99 | pwrite = BOOL_TYPE(false); 100 | if (cmd == tlm::TLM_WRITE_COMMAND) { 101 | memcpy(&tpwdata, data, len); 102 | pwrite = BOOL_TYPE(true); 103 | } 104 | 105 | pwdata = (uint64_t) tpwdata; 106 | 107 | /* Because we wait for events we need to accomodate delay. */ 108 | wait(delay); 109 | delay = SC_ZERO_TIME; 110 | 111 | wait(clk.posedge_event()); 112 | wait(clk.negedge_event()); 113 | /* Access phase. Enable. */ 114 | penable = BOOL_TYPE(true); 115 | 116 | do { 117 | wait(clk.posedge_event()); 118 | /* Readout data. */ 119 | if (cmd == tlm::TLM_READ_COMMAND) { 120 | tprdata = prdata.read().to_uint64(); 121 | memcpy(data, &tprdata, len); 122 | } 123 | 124 | psel = pready == BOOL_TYPE(true) ? BOOL_TYPE(false) : BOOL_TYPE(true); 125 | penable = pready == BOOL_TYPE(true) ? BOOL_TYPE(false) : BOOL_TYPE(true); 126 | } while (pready.read() == BOOL_TYPE(false)); 127 | trans.set_response_status(tlm::TLM_OK_RESPONSE); 128 | } 129 | -------------------------------------------------------------------------------- /trace.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace-utils. 3 | * 4 | * Copyright (c) 2015 Xilinx Inc. 5 | * Written by Edgar E. Iglesias 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "systemc.h" 32 | 33 | using namespace sc_core; 34 | using namespace sc_dt; 35 | using namespace std; 36 | 37 | #include "trace.h" 38 | 39 | template < typename T > void sc_trace_template(sc_trace_file *tf, sc_object *obj) 40 | { 41 | T* object ; 42 | if ((object = dynamic_cast < T* >(obj))) 43 | sc_trace(tf, *object , object->name()); 44 | } 45 | 46 | #define TRACE_TYPE(T, W) \ 47 | do { \ 48 | sc_trace_template < sc_core::sc_signal < T > > (tf,obj); \ 49 | sc_trace_template < sc_core::sc_in < T > > (tf,obj); \ 50 | sc_trace_template < sc_core::sc_out < T > > (tf,obj); \ 51 | } while (0) 52 | 53 | void trace(sc_trace_file* tf, const sc_module& mod, const char *txt) 54 | { 55 | std::vector < sc_object* > ch = mod.get_child_objects(); 56 | 57 | for ( unsigned i = 0; i < ch.size(); i++ ) { 58 | sc_module* m; 59 | sc_object* obj = ch[i]; 60 | 61 | /* Add more types as needed. */ 62 | sc_trace_template < sc_core::sc_signal < bool > > (tf,obj); 63 | sc_trace_template < sc_core::sc_in < bool > > (tf,obj); 64 | sc_trace_template < sc_core::sc_out < bool > > (tf,obj); 65 | 66 | TRACE_TYPE(sc_bv, 2); 67 | TRACE_TYPE(sc_bv, 3); 68 | TRACE_TYPE(sc_bv, 4); 69 | TRACE_TYPE(sc_bv, 5); 70 | TRACE_TYPE(sc_bv, 6); 71 | TRACE_TYPE(sc_bv, 7); 72 | TRACE_TYPE(sc_bv, 8); 73 | TRACE_TYPE(sc_bv, 9); 74 | TRACE_TYPE(sc_bv, 10); 75 | TRACE_TYPE(sc_bv, 16); 76 | TRACE_TYPE(sc_bv, 32); 77 | TRACE_TYPE(sc_bv, 64); 78 | TRACE_TYPE(sc_bv, 128); 79 | TRACE_TYPE(sc_bv, 256); 80 | TRACE_TYPE(sc_bv, 384); 81 | TRACE_TYPE(sc_bv, 512); 82 | TRACE_TYPE(sc_bv, 1024); 83 | 84 | if ((m = dynamic_cast < sc_module* > (obj))) 85 | trace(tf, *m, m->name()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /trace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Trace utils. 3 | * 4 | * Copyright (c) 2015 Xilinx Inc. 5 | * Written by Edgar E. Iglesias 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef TRACE_H__ 27 | #define TRACE_H__ 28 | 29 | void trace(sc_trace_file* tf, const sc_module& mod, const char *txt); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /versal_mrmac_demo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Top level of the Versal MRMAC cosim example. This is based on the VCK190 3 | * MRMAC TRD: 4 | * https://github.com/Xilinx/vck190-ethernet-trd 5 | * 6 | * Copyright (c) 2022 Advanced Micro Devices. 7 | * Written by Edgar E. Iglesias. 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #define SC_INCLUDE_DYNAMIC_PROCESSES 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "systemc.h" 36 | #include "tlm_utils/simple_initiator_socket.h" 37 | #include "tlm_utils/simple_target_socket.h" 38 | #include "tlm_utils/tlm_quantumkeeper.h" 39 | 40 | using namespace sc_core; 41 | using namespace sc_dt; 42 | using namespace std; 43 | 44 | #include "trace.h" 45 | #include "soc/interconnect/iconnect.h" 46 | #include "tests/test-modules/memory.h" 47 | #include "soc/xilinx/versal/xilinx-versal.h" 48 | #include "soc/net/ethernet/xilinx/mrmac/mrmac.h" 49 | #include "soc/dma/xilinx/mcdma/mcdma.h" 50 | 51 | #define NR_MASTERS 3 52 | #define NR_DEVICES 8 53 | 54 | //#define BASE_ADDR 0x28000000ULL 55 | #ifndef BASE_ADDR 56 | #define BASE_ADDR 0xa4000000ULL 57 | #endif 58 | 59 | SC_MODULE(Top) 60 | { 61 | SC_HAS_PROCESS(Top); 62 | iconnect bus; 63 | xilinx_versal versal; 64 | 65 | xilinx_mrmac mac; 66 | xilinx_mcdma dma; 67 | 68 | // Dummy models. 69 | memory gt_ctrl0; 70 | memory gt_ctrl1; 71 | memory gt_ctrl2; 72 | memory gt_ctrl3; 73 | memory gt_pll; 74 | 75 | sc_clock clk; 76 | sc_signal rst, rst_n; 77 | 78 | void pull_reset(void) { 79 | /* Pull the reset signal. */ 80 | rst.write(true); 81 | wait(100, SC_US); 82 | rst.write(false); 83 | wait(100, SC_US); 84 | } 85 | 86 | void gen_rst_n(void) 87 | { 88 | rst_n.write(!rst.read()); 89 | } 90 | 91 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 92 | bus("bus"), 93 | versal("versal", sk_descr, remoteport_tlm_sync_untimed_ptr, true), 94 | mac("mac", true), 95 | dma("dma", 1), 96 | gt_ctrl0("gt_ctrl0", SC_ZERO_TIME, 0x100), 97 | gt_ctrl1("gt_ctrl1", SC_ZERO_TIME, 0x100), 98 | gt_ctrl2("gt_ctrl2", SC_ZERO_TIME, 0x100), 99 | gt_ctrl3("gt_ctrl3", SC_ZERO_TIME, 0x100), 100 | gt_pll("gt_pll", SC_ZERO_TIME, 0x100), 101 | clk("clk", sc_time(20, SC_US)), 102 | rst("rst"), 103 | rst_n("rst_n") 104 | { 105 | SC_THREAD(pull_reset); 106 | 107 | SC_METHOD(gen_rst_n); 108 | sensitive << rst; 109 | 110 | m_qk.set_global_quantum(quantum); 111 | 112 | versal.rst(rst); 113 | mac.rst(rst); 114 | dma.rst(rst); 115 | 116 | bus.memmap(BASE_ADDR + 0x10000ULL, 0x10000 - 1, 117 | ADDRMODE_RELATIVE, -1, mac.reg_socket); 118 | 119 | bus.memmap(BASE_ADDR + 0x20000ULL, 0x1000 - 1, 120 | ADDRMODE_RELATIVE, -1, dma.target_socket); 121 | 122 | bus.memmap(BASE_ADDR + 0x60000ULL, 0x100 - 1, 123 | ADDRMODE_RELATIVE, -1, gt_ctrl0.socket); 124 | 125 | bus.memmap(BASE_ADDR + 0x70000ULL, 0x100 - 1, 126 | ADDRMODE_RELATIVE, -1, gt_ctrl1.socket); 127 | 128 | bus.memmap(BASE_ADDR + 0x80000ULL, 0x100 - 1, 129 | ADDRMODE_RELATIVE, -1, gt_ctrl2.socket); 130 | 131 | bus.memmap(BASE_ADDR + 0x90000ULL, 0x100 - 1, 132 | ADDRMODE_RELATIVE, -1, gt_ctrl3.socket); 133 | 134 | bus.memmap(BASE_ADDR + 0xa0000ULL, 0x100 - 1, 135 | ADDRMODE_RELATIVE, -1, gt_pll.socket); 136 | 137 | bus.memmap(0x0LL, 0xffffffff - 1, 138 | ADDRMODE_RELATIVE, -1, *(versal.s_axi_fpd)); 139 | 140 | versal.m_axi_lpd->bind(*(bus.t_sk[0])); 141 | versal.m_axi_fpd->bind(*(bus.t_sk[1])); 142 | 143 | dma.init_socket.bind(*(bus.t_sk[2])); 144 | 145 | dma.mm2s_stream_socket[0].bind(mac.mac_tx_socket); 146 | mac.mac_rx_socket.bind(dma.s2mm_stream_socket[0]); 147 | 148 | dma.mm2s_irq(versal.pl2ps_irq[0]); 149 | dma.s2mm_irq(versal.pl2ps_irq[1]); 150 | 151 | versal.user_master[0]->bind(mac.phy_rx_socket); 152 | mac.phy_tx_socket.bind(*versal.user_slave[0]); 153 | 154 | versal.tie_off(); 155 | } 156 | 157 | private: 158 | tlm_utils::tlm_quantumkeeper m_qk; 159 | }; 160 | 161 | void usage(void) 162 | { 163 | cout << "tlm socket-path sync-quantum-ns" << endl; 164 | } 165 | 166 | int sc_main(int argc, char* argv[]) 167 | { 168 | Top *top; 169 | uint64_t sync_quantum; 170 | 171 | if (argc < 3) { 172 | sync_quantum = 10000; 173 | } else { 174 | sync_quantum = strtoull(argv[2], NULL, 10); 175 | } 176 | 177 | sc_set_time_resolution(1, SC_PS); 178 | 179 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 180 | 181 | if (argc < 3) { 182 | sc_start(1, SC_PS); 183 | sc_stop(); 184 | usage(); 185 | delete top; 186 | exit(EXIT_FAILURE); 187 | } 188 | 189 | sc_start(); 190 | return 0; 191 | } 192 | -------------------------------------------------------------------------------- /versal_net_cdx_stub.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Top level of the Versal Net CDx stub cosim example. 3 | * 4 | * Copyright (c) 2022 Xilinx Inc. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #define SC_INCLUDE_DYNAMIC_PROCESSES 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "systemc.h" 33 | #include "tlm_utils/simple_initiator_socket.h" 34 | #include "tlm_utils/simple_target_socket.h" 35 | #include "tlm_utils/tlm_quantumkeeper.h" 36 | 37 | using namespace sc_core; 38 | using namespace sc_dt; 39 | using namespace std; 40 | 41 | #include "trace.h" 42 | #include "soc/interconnect/iconnect.h" 43 | #include "debugdev.h" 44 | #include "soc/xilinx/versal-net/xilinx-versal-net.h" 45 | #include "soc/dma/xilinx-cdma.h" 46 | #include "tlm-extensions/genattr.h" 47 | #include "memory.h" 48 | 49 | #define RAM_SIZE (2 * 1024 * 1024) 50 | 51 | #define NR_MASTERS 3 52 | #define NR_DEVICES 7 53 | 54 | class CounterDev : public sc_core::sc_module 55 | { 56 | public: 57 | enum { 58 | R_COUNTER = 0, 59 | }; 60 | 61 | tlm_utils::simple_target_socket tgt_socket; 62 | 63 | CounterDev(sc_core::sc_module_name name) : 64 | sc_module(name), 65 | tgt_socket("tgt-socket"), 66 | r_counter(0) 67 | { 68 | tgt_socket.register_b_transport(this, &CounterDev::b_transport); 69 | } 70 | 71 | private: 72 | virtual void b_transport(tlm::tlm_generic_payload& trans, 73 | sc_time& delay) 74 | { 75 | tlm::tlm_command cmd = trans.get_command(); 76 | unsigned char *data = trans.get_data_ptr(); 77 | unsigned int len = trans.get_data_length(); 78 | uint64_t addr = trans.get_address(); 79 | 80 | if (len != 4 || trans.get_byte_enable_ptr() || 81 | addr != R_COUNTER) { 82 | trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE); 83 | return; 84 | } 85 | 86 | if (trans.get_command() == tlm::TLM_READ_COMMAND) { 87 | memcpy(reinterpret_cast(data), 88 | reinterpret_cast(&r_counter), 89 | len); 90 | 91 | r_counter++; 92 | 93 | } else if (cmd == tlm::TLM_WRITE_COMMAND) { 94 | memcpy(reinterpret_cast(&r_counter), 95 | reinterpret_cast(data), 96 | len); 97 | } 98 | } 99 | 100 | uint32_t r_counter; 101 | }; 102 | 103 | class SMIDdev : public sc_core::sc_module 104 | { 105 | public: 106 | tlm_utils::simple_target_socket tgt_socket; 107 | tlm_utils::simple_initiator_socket init_socket; 108 | 109 | SMIDdev(sc_core::sc_module_name name, uint32_t smid) : 110 | sc_module(name), 111 | tgt_socket("tgt-socket"), 112 | init_socket("init-socket"), 113 | m_smid(smid) 114 | { 115 | tgt_socket.register_b_transport(this, &SMIDdev::b_transport); 116 | } 117 | 118 | private: 119 | virtual void b_transport(tlm::tlm_generic_payload& trans, 120 | sc_time& delay) 121 | { 122 | genattr_extension *genattr; 123 | 124 | trans.get_extension(genattr); 125 | if (!genattr) { 126 | genattr = new genattr_extension(); 127 | trans.set_extension(genattr); 128 | } 129 | 130 | // 131 | // Setup the SMID (master_id) 132 | // 133 | genattr->set_master_id(m_smid); 134 | 135 | init_socket->b_transport(trans, delay); 136 | } 137 | 138 | uint32_t m_smid; 139 | }; 140 | 141 | SC_MODULE(Top) 142 | { 143 | iconnect bus; 144 | xilinx_versal_net versal_net; 145 | debugdev debugdev_cpm; 146 | 147 | memory mem0; 148 | memory mem1; 149 | 150 | xilinx_cdma cdma0; 151 | SMIDdev smid_cdma0; 152 | 153 | xilinx_cdma cdma1; 154 | SMIDdev smid_cdma1; 155 | 156 | CounterDev counter; 157 | sc_signal rst; 158 | 159 | SC_HAS_PROCESS(Top); 160 | 161 | void pull_reset(void) { 162 | /* Pull the reset signal. */ 163 | rst.write(true); 164 | wait(1, SC_US); 165 | rst.write(false); 166 | } 167 | 168 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 169 | sc_module(name), 170 | bus("bus"), 171 | versal_net("versal-net", sk_descr), 172 | debugdev_cpm("debugdev-cpm"), 173 | 174 | mem0("mem0", sc_time(1, SC_NS), RAM_SIZE), 175 | mem1("mem1", sc_time(1, SC_NS), RAM_SIZE), 176 | 177 | cdma0("cdma0"), 178 | smid_cdma0("smid-cdma0", 0x250), 179 | 180 | cdma1("cdma1"), 181 | smid_cdma1("smid-cdma1", 0x251), 182 | 183 | counter("counter"), 184 | rst("rst") 185 | { 186 | m_qk.set_global_quantum(quantum); 187 | 188 | versal_net.rst(rst); 189 | 190 | // 191 | // Bus slave devices 192 | // 193 | // Address Device 194 | // [0xe4000000] : debugdev 195 | // [0xe4020000] : CDMA 0 (SMID 0x250) 196 | // [0xe4030000] : CDMA 1 (SMID 0x251) 197 | // [0xe4040000] : counter 198 | // [0xe4100000] : Memory 2 MB 199 | // [0xe4300000] : Memory 2 MB 200 | // 201 | bus.memmap(0xe4000000ULL, 0x100 - 1, 202 | ADDRMODE_RELATIVE, -1, debugdev_cpm.socket); 203 | bus.memmap(0xe4020000ULL, 0x100 - 1, 204 | ADDRMODE_RELATIVE, -1, cdma0.target_socket); 205 | bus.memmap(0xe4030000ULL, 0x100 - 1, 206 | ADDRMODE_RELATIVE, -1, cdma1.target_socket); 207 | bus.memmap(0xe4040000ULL, 0x100 - 1, 208 | ADDRMODE_RELATIVE, -1, counter.tgt_socket); 209 | bus.memmap(0xe4100000ULL, RAM_SIZE - 1, 210 | ADDRMODE_RELATIVE, -1, mem0.socket); 211 | bus.memmap(0xe4300000ULL, RAM_SIZE - 1, 212 | ADDRMODE_RELATIVE, -1, mem1.socket); 213 | bus.memmap(0x0LL, UINT64_MAX, 214 | ADDRMODE_RELATIVE, -1, *(versal_net.s_cpm)); 215 | 216 | // 217 | // Bus masters 218 | // 219 | versal_net.m_cpm->bind(*(bus.t_sk[0])); 220 | smid_cdma0.init_socket(*(bus.t_sk[1])); 221 | smid_cdma1.init_socket(*(bus.t_sk[2])); 222 | 223 | // 224 | // CDMA0 SMID setup 225 | // 226 | cdma0.init_socket(smid_cdma0.tgt_socket); 227 | 228 | // 229 | // CDMA1 SMID setup 230 | // 231 | cdma1.init_socket(smid_cdma1.tgt_socket); 232 | 233 | /* Connect the PL irqs to the irq_pl_to_ps wires. */ 234 | debugdev_cpm.irq[0](versal_net.pl2ps_irq[0]); 235 | 236 | /* Tie off any remaining unconnected signals. */ 237 | versal_net.tie_off(); 238 | 239 | SC_THREAD(pull_reset); 240 | } 241 | 242 | private: 243 | tlm_utils::tlm_quantumkeeper m_qk; 244 | }; 245 | 246 | void usage(void) 247 | { 248 | cout << "tlm socket-path sync-quantum-ns" << endl; 249 | } 250 | 251 | int sc_main(int argc, char* argv[]) 252 | { 253 | Top *top; 254 | uint64_t sync_quantum; 255 | sc_trace_file *trace_fp = NULL; 256 | 257 | if (argc < 3) { 258 | sync_quantum = 10000; 259 | } else { 260 | sync_quantum = strtoull(argv[2], NULL, 10); 261 | } 262 | 263 | sc_set_time_resolution(1, SC_PS); 264 | 265 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 266 | 267 | if (argc < 3) { 268 | sc_start(1, SC_PS); 269 | sc_stop(); 270 | usage(); 271 | exit(EXIT_FAILURE); 272 | } 273 | 274 | trace_fp = sc_create_vcd_trace_file("trace"); 275 | trace(trace_fp, *top, top->name()); 276 | 277 | sc_start(); 278 | if (trace_fp) { 279 | sc_close_vcd_trace_file(trace_fp); 280 | } 281 | return 0; 282 | } 283 | -------------------------------------------------------------------------------- /versal_net_cdx_stub.md: -------------------------------------------------------------------------------- 1 | # Launching the versal_net_cdx_stub example 2 | 3 | ## Overview 4 | 5 | Instructions for how to co-simulate Xilinx KSB QEMU together with the 6 | versal_net_cdx_stub example are found below. 7 | 8 | ## Overview versal_net_cdx_stub 9 | 10 | The versal_net_cdx_stub contains a [debug device](debugdev.h) at address 11 | 0xe4000000, a [CounterDev](versal_net_cdx_stub.cc#L51) at address 0xe4040000, 12 | 2 [Xilinx CDMA devices] 13 | (https://github.com/Xilinx/libsystemctlm-soc/blob/master/soc/dma/xilinx-cdma.h) 14 | at address 0xe4020000 and 0xe4030000, 2 MB memory at address 0xe4100000 and 15 | also 2MB memory at address 0xe4300000. CDMA device 0 uses SMID 0x250 and CDMA 16 | device 1 uses SMID 0x251. 17 | 18 | 19 | ``` 20 | # 21 | # Code from versal_net_cdx_stub.cc 22 | # 23 | . 24 | . 25 | . 26 | // 27 | // Bus slave devices 28 | // 29 | // Address Device 30 | // [0xe4000000] : debugdev 31 | // [0xe4020000] : CDMA 0 (SMID 0x250) 32 | // [0xe4030000] : CDMA 1 (SMID 0x251) 33 | // [0xe4040000] : counter 34 | // [0xe4100000] : Memory 2 MB 35 | // [0xe4300000] : Memory 2 MB 36 | // 37 | bus.memmap(0xe4000000ULL, 0x100 - 1, 38 | ADDRMODE_RELATIVE, -1, debugdev_cpm.socket); 39 | bus.memmap(0xe4020000ULL, 0x100 - 1, 40 | ADDRMODE_RELATIVE, -1, cdma0.target_socket); 41 | bus.memmap(0xe4030000ULL, 0x100 - 1, 42 | ADDRMODE_RELATIVE, -1, cdma1.target_socket); 43 | bus.memmap(0xe4040000ULL, 0x100 - 1, 44 | ADDRMODE_RELATIVE, -1, counter.tgt_socket); 45 | bus.memmap(0xe4100000ULL, RAM_SIZE - 1, 46 | ADDRMODE_RELATIVE, -1, mem0.socket); 47 | bus.memmap(0xe4300000ULL, RAM_SIZE - 1, 48 | ADDRMODE_RELATIVE, -1, mem1.socket); 49 | . 50 | . 51 | . 52 | ``` 53 | ### debugdev 54 | 55 | Reading the debugdev's register 0 reads out the SystemC simulation time. 56 | Writing to the debugdev's register 0 outputs a debug print in the SystemC 57 | terminal. An example demonstrating how this can be done with the 'devmem' 58 | utility is found below. 59 | 60 | ### CounterDev 61 | 62 | Reading the CounterDev's register 0 reads out the counter value and also 63 | increments the counter after read out. Writing to the CounterDev's register 0 64 | resets the counter to the written value. An example demonstrating how this can 65 | be done with the 'devmem' utility is found below. 66 | 67 | ### Xilinx CDMA 68 | 69 | pg034-axi-cdma.pdf contains more information about how software should interact 70 | with the [Xilinx CDMA devices](https://github.com/Xilinx/libsystemctlm-soc/blob/master/soc/dma/xilinx-cdma.h). 71 | 72 | ## Download and install SystemC 73 | 74 | ``` 75 | $ tar xzf systemc-2.3.2.tar.gz 76 | $ cd systemc-2.3.2 77 | $ CXXFLAGS=-std=c++11 ./configure 78 | $ make 79 | $ make install 80 | ``` 81 | 82 | ## Clone systemctlm-cosim-demo and build the versal_net_cdx_stub 83 | 84 | ``` 85 | $ git clone https://github.com/Xilinx/systemctlm-cosim-demo 86 | $ cd systemctlm-cosim-demo 87 | $ git submodule update --init libsystemctlm-soc 88 | # Replace /path/to/systemc-2.3.2 to where above was installed 89 | $ cat > .config.mk < 30 | 31 | #include "tlm_utils/simple_initiator_socket.h" 32 | #include "tlm_utils/simple_target_socket.h" 33 | 34 | using namespace sc_core; 35 | using namespace std; 36 | 37 | #include "tlm-extensions/genattr.h" 38 | #include "xilinx-axidma.h" 39 | #include 40 | 41 | #define DEBUG_DMA 0 42 | #define D(x) do { \ 43 | if (DEBUG_DMA) { \ 44 | x; \ 45 | } \ 46 | } while (0) 47 | 48 | axidma_mm2s::axidma_mm2s(sc_module_name name, bool use_memcpy) 49 | : axidma(name, use_memcpy), stream_socket("stream-socket") 50 | { 51 | } 52 | 53 | axidma_s2mm::axidma_s2mm(sc_module_name name, bool use_memcpy) 54 | : axidma(name, use_memcpy), stream_socket("stream-socket") 55 | { 56 | stream_socket.register_b_transport(this, &axidma_s2mm::s_b_transport); 57 | } 58 | 59 | axidma::axidma(sc_module_name name, bool use_memcpy) 60 | : sc_module(name), tgt_socket("tgt-socket"), irq("irq"), 61 | use_memcpy(use_memcpy) 62 | { 63 | tgt_socket.register_b_transport(this, &axidma::b_transport); 64 | memset(®s, 0, sizeof regs); 65 | 66 | SC_METHOD(update_irqs); 67 | dont_initialize(); 68 | sensitive << ev_update_irqs; 69 | SC_THREAD(do_dma_copy); 70 | } 71 | 72 | void axidma::do_dma_trans(tlm::tlm_command cmd, unsigned char *buf, 73 | sc_dt::uint64 addr, sc_dt::uint64 len, 74 | sc_time &delay) 75 | { 76 | tlm::tlm_generic_payload tr; 77 | 78 | tr.set_command(cmd); 79 | tr.set_address(addr); 80 | tr.set_data_ptr(buf); 81 | tr.set_data_length(len); 82 | tr.set_streaming_width(len); 83 | tr.set_dmi_allowed(false); 84 | tr.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); 85 | 86 | init_socket->b_transport(tr, delay); 87 | if (tr.get_response_status() != tlm::TLM_OK_RESPONSE) { 88 | printf("%s:%d DMA transaction error!\n", __func__, __LINE__); 89 | } 90 | } 91 | 92 | void axidma_mm2s::do_stream_trans(tlm::tlm_command cmd, unsigned char *buf, 93 | sc_dt::uint64 addr, sc_dt::uint64 len, bool eop, 94 | sc_time &delay) 95 | { 96 | tlm::tlm_generic_payload tr; 97 | genattr_extension *genattr = new genattr_extension(); 98 | 99 | tr.set_command(cmd); 100 | tr.set_address(addr); 101 | tr.set_data_ptr(buf); 102 | tr.set_data_length(len); 103 | tr.set_streaming_width(len); 104 | tr.set_dmi_allowed(false); 105 | tr.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); 106 | 107 | genattr->set_eop(eop); 108 | tr.set_extension(genattr); 109 | 110 | stream_socket->b_transport(tr, delay); 111 | if (tr.get_response_status() != tlm::TLM_OK_RESPONSE) { 112 | printf("%s:%d DMA transaction error!\n", __func__, __LINE__); 113 | } 114 | 115 | tr.release_extension(genattr); 116 | } 117 | 118 | void axidma::update_irqs(void) 119 | { 120 | D(printf("DMA irq=%d\n", regs.sr & regs.cr & AXIDMA_CR_IOC_IRQ_EN)); 121 | irq.write(regs.sr & regs.cr & AXIDMA_CR_IOC_IRQ_EN); 122 | } 123 | 124 | void axidma_s2mm::do_dma_copy(void) {} 125 | 126 | void axidma_mm2s::do_dma_copy(void) 127 | { 128 | while (1) { 129 | unsigned char buf[2 * 1024]; 130 | uint64_t addr; 131 | sc_time delay = SC_ZERO_TIME; 132 | unsigned int tlen; 133 | bool eop; 134 | 135 | if (!regs.length) { 136 | wait(ev_dma_copy); 137 | } 138 | 139 | assert(!(regs.sr & AXIDMA_SR_IDLE)); 140 | tlen = regs.length > sizeof buf ? sizeof buf : regs.length; 141 | eop = tlen == regs.length; 142 | 143 | addr = regs.addr_msb; 144 | addr <<= 32; 145 | addr += regs.addr; 146 | 147 | if (use_memcpy) { 148 | memcpy(buf, (void *) addr, tlen); 149 | } else { 150 | do_dma_trans(tlm::TLM_READ_COMMAND, buf, addr, tlen, delay); 151 | } 152 | do_stream_trans(tlm::TLM_WRITE_COMMAND, buf, addr, tlen, eop, delay); 153 | 154 | addr += tlen; 155 | regs.length -= tlen; 156 | 157 | regs.addr = addr; 158 | regs.addr_msb = addr >> 32; 159 | 160 | if (regs.length == 0) { 161 | /* If the DMA was running, signal done. */ 162 | regs.sr |= AXIDMA_SR_IDLE | AXIDMA_SR_IOC_IRQ; 163 | ev_update_irqs.notify(); 164 | } 165 | } 166 | } 167 | 168 | void axidma::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) 169 | { 170 | tlm::tlm_command cmd = trans.get_command(); 171 | sc_dt::uint64 addr = trans.get_address(); 172 | unsigned char* data = trans.get_data_ptr(); 173 | unsigned int len = trans.get_data_length(); 174 | unsigned char* byt = trans.get_byte_enable_ptr(); 175 | unsigned int wid = trans.get_streaming_width(); 176 | 177 | if (byt != 0) { 178 | trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE); 179 | return; 180 | } 181 | 182 | if (len > 4 || wid < len) { 183 | trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE); 184 | return; 185 | } 186 | 187 | addr >>= 2; 188 | if (trans.get_command() == tlm::TLM_READ_COMMAND) { 189 | memcpy(data, ®s.u32[addr], len); 190 | } else if (cmd == tlm::TLM_WRITE_COMMAND) { 191 | uint32_t v; 192 | memcpy(&v, data, len); 193 | switch (addr) { 194 | case AXIDMA_R_SR: 195 | regs.u32[addr] &= ~(v & AXIDMA_SR_IOC_IRQ); 196 | D(printf("%s: SR=%x.%x val=%x\n", name(), 197 | regs.sr, regs.u32[addr], v)); 198 | break; 199 | case AXIDMA_R_LENGTH: 200 | length_copied = 0; 201 | regs.length = v; 202 | regs.sr &= ~(AXIDMA_SR_IDLE); 203 | D(printf("%s: write LENGTH %d\n", 204 | name(), regs.length)); 205 | ev_dma_copy.notify(); 206 | break; 207 | default: 208 | /* No side-effect. */ 209 | regs.u32[addr] = v; 210 | break; 211 | } 212 | } 213 | ev_update_irqs.notify(); 214 | trans.set_response_status(tlm::TLM_OK_RESPONSE); 215 | } 216 | 217 | void axidma_s2mm::s_b_transport(tlm::tlm_generic_payload& trans, 218 | sc_time& delay) 219 | { 220 | unsigned char *data = trans.get_data_ptr(); 221 | unsigned int len = trans.get_data_length(); 222 | genattr_extension *genattr; 223 | unsigned int len_to_copy; 224 | uint64_t addr; 225 | bool eop = true; 226 | 227 | trans.get_extension(genattr); 228 | if (genattr) { 229 | eop = genattr->get_eop(); 230 | } 231 | 232 | if (regs.sr & AXIDMA_SR_IDLE) { 233 | /* Put back-pressure. */ 234 | D(printf("%s: DMA IS IDLE length=%x\n", 235 | name(), regs.length)); 236 | do { 237 | wait(ev_dma_copy); 238 | } while (regs.sr & AXIDMA_SR_IDLE); 239 | } 240 | 241 | addr = regs.addr_msb; 242 | addr <<= 32; 243 | addr += regs.addr; 244 | 245 | len_to_copy = regs.length >= len ? len : regs.length; 246 | 247 | if (use_memcpy) { 248 | memcpy((void *) addr, data, len_to_copy); 249 | } else { 250 | do_dma_trans(tlm::TLM_WRITE_COMMAND, data, addr, 251 | len_to_copy, delay); 252 | } 253 | 254 | length_copied += len_to_copy; 255 | addr += len_to_copy; 256 | regs.length -= len_to_copy; 257 | regs.addr_msb = addr >> 32; 258 | regs.addr = addr; 259 | 260 | if (regs.length == 0 || eop) { 261 | regs.sr |= AXIDMA_SR_IDLE | AXIDMA_SR_IOC_IRQ; 262 | regs.length = length_copied; 263 | } 264 | 265 | ev_update_irqs.notify(); 266 | trans.set_response_status(tlm::TLM_OK_RESPONSE); 267 | } 268 | -------------------------------------------------------------------------------- /xilinx-axidma.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Xilinx Inc. 3 | * Written by Edgar E. Iglesias. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | enum { 25 | AXIDMA_CR_RS = 1 << 0, 26 | AXIDMA_CR_RESET = 1 << 2, 27 | AXIDMA_CR_KEYHOLE = 1 << 3, 28 | AXIDMA_CR_CYCLIC_BD = 1 << 4, 29 | AXIDMA_CR_IOC_IRQ_EN = 1 << 12, 30 | }; 31 | 32 | enum { 33 | AXIDMA_SR_HALTED = 1 << 0, 34 | AXIDMA_SR_IDLE = 1 << 1, 35 | AXIDMA_SR_SGINCLD = 1 << 3, 36 | AXIDMA_SR_IOC_IRQ = 1 << 12, 37 | }; 38 | 39 | enum { 40 | AXIDMA_R_CR = 0x00 / 4, 41 | AXIDMA_R_SR = 0x04 / 4, 42 | AXIDMA_R_ADDR = 0x18 / 4, 43 | AXIDMA_R_ADDR_MSB = 0x1c / 4, 44 | AXIDMA_R_LENGTH = 0x28 / 4, 45 | AXIDMA_R_MAX = 0x2c / 4, 46 | }; 47 | 48 | /* Base class common to both the mm2s and s2mm channels. */ 49 | class axidma 50 | : public sc_core::sc_module 51 | { 52 | public: 53 | tlm_utils::simple_initiator_socket init_socket; 54 | tlm_utils::simple_target_socket tgt_socket; 55 | 56 | sc_out irq; 57 | axidma(sc_core::sc_module_name name, bool use_memcpy = false); 58 | SC_HAS_PROCESS(axidma); 59 | protected: 60 | union { 61 | struct { 62 | uint32_t cr; 63 | uint32_t sr; 64 | uint32_t rsv0[AXIDMA_R_ADDR - AXIDMA_R_SR - 1]; 65 | uint32_t addr; 66 | uint32_t addr_msb; 67 | uint32_t rsv1[AXIDMA_R_LENGTH - AXIDMA_R_ADDR_MSB - 1]; 68 | uint32_t length; 69 | }; 70 | uint32_t u32[AXIDMA_R_MAX]; 71 | } regs; 72 | // S2M needs to keep track of the number of bytes actually copied. 73 | uint32_t length_copied; 74 | 75 | bool use_memcpy; 76 | 77 | sc_event ev_update_irqs; 78 | sc_event ev_dma_copy; 79 | virtual void do_dma_copy(void) {}; 80 | void do_dma_trans(tlm::tlm_command cmd, unsigned char *buf, 81 | sc_dt::uint64 addr, sc_dt::uint64 len, sc_time &delay); 82 | void update_irqs(void); 83 | 84 | private: 85 | virtual void b_transport(tlm::tlm_generic_payload& trans, sc_time& delay); 86 | }; 87 | 88 | class axidma_mm2s : public axidma 89 | { 90 | public: 91 | tlm_utils::simple_initiator_socket stream_socket; 92 | axidma_mm2s(sc_core::sc_module_name name, bool use_memcpy = false); 93 | protected: 94 | virtual void do_dma_copy(void); 95 | private: 96 | void do_stream_trans(tlm::tlm_command cmd, unsigned char *buf, 97 | sc_dt::uint64 addr, sc_dt::uint64 len, bool eop, sc_time &delay); 98 | }; 99 | 100 | class axidma_s2mm : public axidma 101 | { 102 | public: 103 | tlm_utils::simple_target_socket stream_socket; 104 | axidma_s2mm(sc_core::sc_module_name name, bool use_memcpy = false); 105 | protected: 106 | virtual void do_dma_copy(void); 107 | private: 108 | void s_b_transport(tlm::tlm_generic_payload& trans, sc_time& delay); 109 | }; 110 | -------------------------------------------------------------------------------- /zynq_demo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Top level of the Zynq cosim example. 3 | * 4 | * Copyright (c) 2014 Xilinx Inc. 5 | * Written by Edgar E. Iglesias 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #define SC_INCLUDE_DYNAMIC_PROCESSES 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "systemc.h" 34 | #include "tlm_utils/simple_initiator_socket.h" 35 | #include "tlm_utils/simple_target_socket.h" 36 | #include "tlm_utils/tlm_quantumkeeper.h" 37 | 38 | using namespace sc_core; 39 | using namespace sc_dt; 40 | using namespace std; 41 | 42 | #include "trace.h" 43 | #include "soc/interconnect/iconnect.h" 44 | #include "debugdev.h" 45 | #include "soc/xilinx/zynq/xilinx-zynq.h" 46 | 47 | #define NR_MASTERS 1 48 | #define NR_DEVICES 1 49 | 50 | SC_MODULE(Top) 51 | { 52 | iconnect bus; 53 | xilinx_zynq zynq; 54 | debugdev debug; 55 | sc_signal rst; 56 | 57 | SC_HAS_PROCESS(Top); 58 | 59 | void pull_reset(void) { 60 | /* Pull the reset signal. */ 61 | rst.write(true); 62 | wait(1, SC_US); 63 | rst.write(false); 64 | } 65 | 66 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 67 | bus("bus"), 68 | zynq("zynq", sk_descr), 69 | debug("debug"), 70 | rst("rst") 71 | { 72 | m_qk.set_global_quantum(quantum); 73 | 74 | zynq.rst(rst); 75 | 76 | bus.memmap(0x40000000ULL, 0x100 - 1, 77 | ADDRMODE_RELATIVE, -1, debug.socket); 78 | 79 | zynq.m_axi_gp[0]->bind(*(bus.t_sk[0])); 80 | 81 | /* Connect the PL irqs to the irq_pl_to_ps wires. */ 82 | debug.irq[0](zynq.pl2ps_irq[0]); 83 | 84 | /* Tie off any remaining unconnected signals. */ 85 | zynq.tie_off(); 86 | 87 | SC_THREAD(pull_reset); 88 | } 89 | 90 | private: 91 | tlm_utils::tlm_quantumkeeper m_qk; 92 | }; 93 | 94 | void usage(void) 95 | { 96 | cout << "tlm socket-path sync-quantum-ns" << endl; 97 | } 98 | 99 | int sc_main(int argc, char* argv[]) 100 | { 101 | Top *top; 102 | uint64_t sync_quantum; 103 | sc_trace_file *trace_fp = NULL; 104 | 105 | if (argc < 3) { 106 | sync_quantum = 10000; 107 | } else { 108 | sync_quantum = strtoull(argv[2], NULL, 10); 109 | } 110 | 111 | sc_set_time_resolution(1, SC_PS); 112 | 113 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 114 | 115 | if (argc < 3) { 116 | sc_start(1, SC_PS); 117 | sc_stop(); 118 | usage(); 119 | exit(EXIT_FAILURE); 120 | } 121 | 122 | trace_fp = sc_create_vcd_trace_file("trace"); 123 | trace(trace_fp, *top, top->name()); 124 | 125 | sc_start(); 126 | if (trace_fp) { 127 | sc_close_vcd_trace_file(trace_fp); 128 | } 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /zynqmp_lmac2_demo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Top level of the ZynqMP LMAC_CORE2 cosim example. 3 | * 4 | * Copyright (c) 2019 Xilinx Inc. 5 | * Written by Edgar E. Iglesias and Francisco Iglesias. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #define SC_INCLUDE_DYNAMIC_PROCESSES 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "systemc.h" 34 | #include "tlm_utils/simple_initiator_socket.h" 35 | #include "tlm_utils/simple_target_socket.h" 36 | #include "tlm_utils/tlm_quantumkeeper.h" 37 | 38 | using namespace sc_core; 39 | using namespace sc_dt; 40 | using namespace std; 41 | 42 | #include "trace.h" 43 | #include "soc/interconnect/iconnect.h" 44 | #include "xilinx-axidma.h" 45 | #include "soc/xilinx/zynqmp/xilinx-zynqmp.h" 46 | 47 | #include "tlm-bridges/tlm2apb-bridge.h" 48 | #include "tlm-bridges/tlm2axis-bridge.h" 49 | #include "tlm-bridges/axis2tlm-bridge.h" 50 | #include "tlm-xgmii-phy.h" 51 | 52 | #ifdef HAVE_VERILOG_VERILATOR 53 | #include 54 | #include "Vlmac_wrapper_top.h" 55 | #include "verilated.h" 56 | #endif 57 | 58 | #define NR_MASTERS 3 59 | #define NR_DEVICES 4 60 | 61 | #ifndef BASE_ADDR 62 | #define BASE_ADDR 0xa0000000ULL 63 | #endif 64 | 65 | SC_MODULE(Top) 66 | { 67 | SC_HAS_PROCESS(Top); 68 | iconnect *bus; 69 | xilinx_zynqmp zynq; 70 | 71 | axidma_mm2s dma_mm2s_A; 72 | axidma_s2mm dma_s2mm_C; 73 | 74 | tlm2axis_bridge<64> tlm2axis; 75 | axis2tlm_bridge<64> axis2tlm; 76 | 77 | sc_signal rst, rst_n; 78 | 79 | sc_clock *clk; 80 | 81 | tlm2apb_bridge *tlm2apb_lmac; 82 | 83 | Vlmac_wrapper_top *lmac; 84 | tlm_xgmii_phy phy; 85 | 86 | sc_signal > phy_txd; 87 | sc_signal > phy_txc; 88 | sc_signal > phy_rxd; 89 | sc_signal > phy_rxc; 90 | 91 | sc_signal > tx_axis_mac_tdata; 92 | sc_signal > tx_axis_mac_tstrb; 93 | sc_signal tx_axis_mac_tvalid; 94 | sc_signal tx_axis_mac_tlast; 95 | sc_signal tx_axis_mac_tuser; 96 | sc_signal tx_axis_mac_tready; 97 | 98 | sc_signal > rx_axis_mac_tdata; 99 | sc_signal > rx_axis_mac_tstrb; 100 | sc_signal rx_axis_mac_tvalid; 101 | sc_signal rx_axis_mac_tlast; 102 | sc_signal rx_axis_mac_tuser; 103 | sc_signal rx_axis_mac_tready; 104 | 105 | sc_signal apbsig_lmac_psel; 106 | sc_signal apbsig_lmac_penable; 107 | sc_signal apbsig_lmac_pwrite; 108 | sc_signal apbsig_lmac_pready; 109 | sc_signal > apbsig_lmac_paddr; 110 | sc_signal > apbsig_lmac_pwdata; 111 | sc_signal > apbsig_lmac_prdata; 112 | 113 | sc_signal apbsig_timer_psel; 114 | sc_signal apbsig_timer_penable; 115 | sc_signal apbsig_timer_pwrite; 116 | sc_signal apbsig_timer_pready; 117 | sc_signal > apbsig_timer_paddr; 118 | sc_signal > apbsig_timer_pwdata; 119 | sc_signal > apbsig_timer_prdata; 120 | 121 | void gen_rst_n(void) 122 | { 123 | rst_n.write(!rst.read()); 124 | } 125 | 126 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 127 | zynq("zynq", sk_descr, remoteport_tlm_sync_untimed_ptr, false), 128 | dma_mm2s_A("dma_mm2s_A"), 129 | dma_s2mm_C("dma_s2mm_C"), 130 | tlm2axis("tlm2axis"), 131 | axis2tlm("axis2tlm"), 132 | rst("rst"), 133 | rst_n("rst_n"), 134 | 135 | phy("phy"), 136 | phy_txd("phy_txd"), 137 | phy_txc("phy_txc"), 138 | phy_rxd("phy_rxd"), 139 | phy_rxc("phy_rxc"), 140 | 141 | tx_axis_mac_tdata("tx_axis_mac_tdata"), 142 | tx_axis_mac_tstrb("tx_axis_mac_tstrb"), 143 | tx_axis_mac_tvalid("tx_axis_mac_tvalid"), 144 | tx_axis_mac_tlast("tx_axis_mac_tlast"), 145 | tx_axis_mac_tuser("tx_axis_mac_tuser"), 146 | tx_axis_mac_tready("tx_axis_mac_tready"), 147 | 148 | rx_axis_mac_tdata("rx_axis_mac_tdata"), 149 | rx_axis_mac_tstrb("rx_axis_mac_tstrb"), 150 | rx_axis_mac_tvalid("rx_axis_mac_tvalid"), 151 | rx_axis_mac_tlast("rx_axis_mac_tlast"), 152 | rx_axis_mac_tuser("rx_axis_mac_tuser"), 153 | rx_axis_mac_tready("rx_axis_mac_tready"), 154 | 155 | apbsig_lmac_psel("apblmac_psel"), 156 | apbsig_lmac_penable("apblmac_penable"), 157 | apbsig_lmac_pwrite("apblmac_pwrite"), 158 | apbsig_lmac_pready("apblmac_pready"), 159 | apbsig_lmac_paddr("apblmac_paddr"), 160 | apbsig_lmac_pwdata("apblmac_pwdata"), 161 | apbsig_lmac_prdata("apblmac_prdata"), 162 | 163 | apbsig_timer_psel("apbtimer_psel"), 164 | apbsig_timer_penable("apbtimer_penable"), 165 | apbsig_timer_pwrite("apbtimer_pwrite"), 166 | apbsig_timer_pready("apbtimer_pready"), 167 | apbsig_timer_paddr("apbtimer_paddr"), 168 | apbsig_timer_pwdata("apbtimer_pwdata"), 169 | apbsig_timer_prdata("apbtimer_prdata") 170 | { 171 | unsigned int i; 172 | 173 | SC_METHOD(gen_rst_n); 174 | sensitive << rst; 175 | 176 | m_qk.set_global_quantum(quantum); 177 | 178 | zynq.rst(rst); 179 | 180 | bus = new iconnect ("bus"); 181 | 182 | tlm2apb_lmac = new tlm2apb_bridge ("tlm2apb-lmac-bridge"); 183 | bus->memmap(BASE_ADDR + 0x30000ULL, 0x4000 - 1, 184 | ADDRMODE_RELATIVE, -1, tlm2apb_lmac->tgt_socket); 185 | 186 | bus->memmap(BASE_ADDR + 0x34000ULL, 0x100 - 1, 187 | ADDRMODE_RELATIVE, -1, dma_mm2s_A.tgt_socket); 188 | bus->memmap(BASE_ADDR + 0x35000ULL, 0x100 - 1, 189 | ADDRMODE_RELATIVE, -1, dma_s2mm_C.tgt_socket); 190 | 191 | bus->memmap(0x0LL, 0xffffffff - 1, 192 | ADDRMODE_RELATIVE, -1, *(zynq.s_axi_hpc_fpd[0])); 193 | 194 | zynq.s_axi_hpm_fpd[0]->bind(*(bus->t_sk[0])); 195 | 196 | dma_mm2s_A.init_socket.bind(*(bus->t_sk[1])); 197 | dma_s2mm_C.init_socket.bind(*(bus->t_sk[2])); 198 | 199 | dma_mm2s_A.stream_socket.bind(tlm2axis.tgt_socket); 200 | axis2tlm.socket.bind(dma_s2mm_C.stream_socket); 201 | 202 | dma_mm2s_A.irq(zynq.pl2ps_irq[2]); 203 | dma_s2mm_C.irq(zynq.pl2ps_irq[4]); 204 | 205 | /* Slow clock to keep simulation fast. */ 206 | clk = new sc_clock("clk", sc_time(10, SC_US)); 207 | lmac = new Vlmac_wrapper_top("lmac"); 208 | 209 | tlm2axis.clk(*clk); 210 | tlm2axis.resetn(rst_n); 211 | tlm2axis.tvalid(tx_axis_mac_tvalid); 212 | tlm2axis.tready(tx_axis_mac_tready); 213 | tlm2axis.tdata(tx_axis_mac_tdata); 214 | tlm2axis.tstrb(tx_axis_mac_tstrb); 215 | tlm2axis.tuser(tx_axis_mac_tuser); 216 | tlm2axis.tlast(tx_axis_mac_tlast); 217 | 218 | axis2tlm.clk(*clk); 219 | axis2tlm.resetn(rst_n); 220 | axis2tlm.tvalid(rx_axis_mac_tvalid); 221 | axis2tlm.tready(rx_axis_mac_tready); 222 | axis2tlm.tdata(rx_axis_mac_tdata); 223 | axis2tlm.tstrb(rx_axis_mac_tstrb); 224 | axis2tlm.tuser(rx_axis_mac_tuser); 225 | axis2tlm.tlast(rx_axis_mac_tlast); 226 | 227 | lmac->clk(*clk); 228 | lmac->rst_n(rst_n); 229 | lmac->xgmii_txd(phy_txd); 230 | lmac->xgmii_txc(phy_txc); 231 | lmac->xgmii_rxd(phy_rxd); 232 | lmac->xgmii_rxc(phy_rxc); 233 | lmac->host_addr_reg(apbsig_lmac_paddr); 234 | lmac->reg_rd_start(apbsig_lmac_psel); 235 | lmac->reg_rd_done_out(apbsig_lmac_pready); 236 | lmac->FMAC_REGDOUT(apbsig_lmac_prdata); 237 | 238 | lmac->tx_axis_mac_tdata(tx_axis_mac_tdata); 239 | lmac->tx_axis_mac_tvalid(tx_axis_mac_tvalid); 240 | lmac->tx_axis_mac_tlast(tx_axis_mac_tlast); 241 | lmac->tx_axis_mac_tuser(tx_axis_mac_tuser); 242 | lmac->tx_axis_mac_tready(tx_axis_mac_tready); 243 | lmac->tx_axis_mac_tstrb(tx_axis_mac_tstrb); 244 | 245 | lmac->rx_axis_mac_tdata(rx_axis_mac_tdata); 246 | lmac->rx_axis_mac_tvalid(rx_axis_mac_tvalid); 247 | lmac->rx_axis_mac_tlast(rx_axis_mac_tlast); 248 | lmac->rx_axis_mac_tuser(rx_axis_mac_tuser); 249 | lmac->rx_axis_mac_tready(rx_axis_mac_tready); 250 | lmac->rx_axis_mac_tstrb(rx_axis_mac_tstrb); 251 | 252 | phy.tx.clk(*clk); 253 | phy.tx.xxd(phy_txd); 254 | phy.tx.xxc(phy_txc); 255 | 256 | phy.rx.clk(*clk); 257 | phy.rx.xxd(phy_rxd); 258 | phy.rx.xxc(phy_rxc); 259 | 260 | zynq.user_master[0]->bind(phy.rx.tgt_socket); 261 | phy.tx.init_socket.bind(*zynq.user_slave[0]); 262 | 263 | tlm2apb_lmac->clk(*clk); 264 | tlm2apb_lmac->psel(apbsig_lmac_psel); 265 | tlm2apb_lmac->penable(apbsig_lmac_penable); 266 | tlm2apb_lmac->pwrite(apbsig_lmac_pwrite); 267 | tlm2apb_lmac->paddr(apbsig_lmac_paddr); 268 | tlm2apb_lmac->pwdata(apbsig_lmac_pwdata); 269 | tlm2apb_lmac->prdata(apbsig_lmac_prdata); 270 | tlm2apb_lmac->pready(apbsig_lmac_pready); 271 | 272 | zynq.tie_off(); 273 | } 274 | 275 | private: 276 | tlm_utils::tlm_quantumkeeper m_qk; 277 | }; 278 | 279 | void usage(void) 280 | { 281 | cout << "tlm socket-path sync-quantum-ns" << endl; 282 | } 283 | 284 | int sc_main(int argc, char* argv[]) 285 | { 286 | Top *top; 287 | uint64_t sync_quantum; 288 | sc_trace_file *trace_fp = NULL; 289 | 290 | #if HAVE_VERILOG_VERILATOR 291 | Verilated::commandArgs(argc, argv); 292 | #endif 293 | 294 | if (argc < 3) { 295 | sync_quantum = 10000; 296 | } else { 297 | sync_quantum = strtoull(argv[2], NULL, 10); 298 | } 299 | 300 | sc_set_time_resolution(1, SC_PS); 301 | 302 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 303 | 304 | if (argc < 3) { 305 | sc_start(1, SC_PS); 306 | sc_stop(); 307 | usage(); 308 | exit(EXIT_FAILURE); 309 | } 310 | 311 | trace_fp = sc_create_vcd_trace_file("trace"); 312 | trace(trace_fp, *top, top->name()); 313 | 314 | #if VM_TRACE 315 | Verilated::traceEverOn(true); 316 | // If verilator was invoked with --trace argument, 317 | // and if at run time passed the +trace argument, turn on tracing 318 | VerilatedVcdSc* tfp = NULL; 319 | const char* flag = Verilated::commandArgsPlusMatch("trace"); 320 | if (flag && 0 == strcmp(flag, "+trace")) { 321 | tfp = new VerilatedVcdSc; 322 | top->lmac->trace(tfp, 99); 323 | tfp->open("vlt_dump.vcd"); 324 | } 325 | #endif 326 | 327 | /* Pull the reset signal. */ 328 | top->rst.write(true); 329 | sc_start(1, SC_US); 330 | top->rst.write(false); 331 | 332 | sc_start(); 333 | if (trace_fp) { 334 | sc_close_vcd_trace_file(trace_fp); 335 | } 336 | 337 | #if VM_TRACE 338 | if (tfp) { tfp->close(); tfp = NULL; } 339 | #endif 340 | return 0; 341 | } 342 | -------------------------------------------------------------------------------- /zynqmp_lmac2_ipxact_demo.txt: -------------------------------------------------------------------------------- 1 | ZynqMP LMAC2 IP-XACt DEMO 2 | ------------------------- 3 | 4 | The ZynqMP LMAC2 IP-XACT DEMO co-simulates QEMU and SystemC, where QEMU 5 | emulates the hardened part (PS) of the ZynqMP and SystemC simulates the 6 | programmable logic (PL) side of the system. The sides communicate through 7 | the remote port protocol [3]. The PL side in this demo contains an 8 | instance of the Lewiz LMAC CORE2 Ethernet MAC and connects it to the PS 9 | side through an interconnect and AXIStream DMAs. Also a PHY is 10 | instantiated on the PL side, the PHY injects traffic coming from QEMU into 11 | LMAC CORE2 and forwards outgoing traffic from the LMAC CORE2 to QEMU. 12 | 13 | To note is that the LMAC CORE2 is a verilog RTL component translated into 14 | SystemC using a tool named verilator [5] before the final simulator is 15 | created. 16 | 17 | systemctlm-cosim-demo [1] contains the IP-XACT description of the demo. 18 | This description can be displayed using a graphical EDA tool based on the 19 | IP-XACT standard, an open source example of an IP-XACT based tool is 20 | kactus2 [4]. 21 | 22 | libsystemctlm-soc [2] contains a tool named pysimgen that is able to 23 | translate IP-XACT descriptions into QEMU / SystemC co-simulations. 24 | 25 | A modified version of kactus2 [7] is able to launch libsystemctlm-soc's 26 | pysimgen and autogenerate the demo co-simulation through a button press. 27 | 28 | Requirements for running the demo 29 | --------------------------------- 30 | 31 | * A working QEMU / SystemC co-simulation environment (see the README in 32 | [1], [2] and [3] for how to install one) 33 | 34 | * Verilator 35 | 36 | * kactus2, the modified version [7] 37 | 38 | * A Linux kernel containing a driver for the Lewiz LMAC CORE2 Ethernet MAC [8] 39 | 40 | Steps for translating the demo into a co-simulation using kactus2 41 | ----------------------------------------------------------------- 42 | 43 | * Clone the following two git repos: 44 | 45 | 1 - git clone https://github.com/Xilinx/libsystemctlm-soc.git 46 | 2 - git clone https://github.com/Xilinx/systemctlm-cosim-demo.git 47 | 48 | * Launch kactus2 (the modified version) 49 | 50 | * Click the button 'Configure Library' 51 | 52 | * Add following two paths by clicking on the plus sign: 53 | 54 | 1 /path/to/libsystemctlm-soc/packages/ipxact 55 | 1 /path/to/systemctlm-cosim-demo/ 56 | 57 | * Click on the 'POSH Configuration' button 58 | 59 | * In 'Script File' insert the path to the pysimgen script: 60 | 61 | /path/to/libsystemctlm-soc/tools/pysimgen/pysimgen 62 | 63 | * In kactus2 open the ZynqMP LMAC2 demo HW design 64 | 65 | * In the VLNV tree: 66 | 67 | 1 Click on the 'xilinx.com -> demos -> zynqmp_lmac2_demo' 68 | 69 | 2 Right click on the demo version and choose 'Open HW 70 | design' 71 | 72 | * Click on the 'xilinx_zynqmp_0' instance 73 | 74 | * In the 'configurable element values' change the value of the following 75 | parameters: 76 | 77 | * EMULATOR 78 | 79 | - This is the QEMU binary to use 80 | 81 | * EMULATOR_ARGS 82 | 83 | - This are the command line arguments passed on to QEMU. 84 | This is were configuration of kernel images, dtbs etc is 85 | done. The demo contains an example of this line. 86 | 87 | * SK_DESCR 88 | 89 | - The socket path where the SystemC side and QEMU will 90 | connect to each other (see [3] for information). The 91 | demo contains an example of this line. 92 | 93 | * Click on the POSH simulation button 94 | 95 | * This will autogenerate the SystemC code for the demo including a 96 | QEMU launcher, then build and run it. 97 | 98 | Eclipse Mixed HW / SW Debugging Environment 99 | ------------------------------------------- 100 | 101 | Using the wave_viewer project [6] it is possible to debug the generated 102 | and launched demo co-simulation from inside Eclipse. Instructions on how 103 | to setup an Eclipse Mixed HW / SW Debugging Environment and how to attach 104 | from inside Eclipse to a running QEMU / SystemC co-simulation can be found 105 | in [6]. 106 | 107 | References 108 | ---------- 109 | [1] https://github.com/Xilinx/systemctlm-cosim-demo.git 110 | [2] https://github.com/Xilinx/libsystemctlm-soc.git 111 | [3] https://www.xilinx.com/support/documentation/sw_manuals/xilinx2018_2/ug1169-xilinx-qemu.pdf 112 | [4] https://github.com/kactus2/kactus2dev 113 | [5] https://www.veripool.org/wiki/verilator 114 | [6] https://github.com/edgarigl/wave_viewer 115 | [7] https://github.com/spanou/kactus2dev 116 | [8] https://github.com/edgarigl/linux/tree/posh-lmac 117 | -------------------------------------------------------------------------------- /zynqmp_lmac3_demo.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Top level of the ZynqMP LMAC_CORE2 cosim example. 3 | * 4 | * Copyright (c) 2019 Xilinx Inc. 5 | * Written by Edgar E. Iglesias and Francisco Iglesias. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #define SC_INCLUDE_DYNAMIC_PROCESSES 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "systemc.h" 34 | #include "tlm_utils/simple_initiator_socket.h" 35 | #include "tlm_utils/simple_target_socket.h" 36 | #include "tlm_utils/tlm_quantumkeeper.h" 37 | 38 | using namespace sc_core; 39 | using namespace sc_dt; 40 | using namespace std; 41 | 42 | #include "trace.h" 43 | #include "soc/interconnect/iconnect.h" 44 | #include "xilinx-axidma.h" 45 | #include "soc/xilinx/zynqmp/xilinx-zynqmp.h" 46 | 47 | #include "tlm-bridges/tlm2apb-bridge.h" 48 | #include "tlm-bridges/tlm2axis-bridge.h" 49 | #include "tlm-bridges/axis2tlm-bridge.h" 50 | #include "tlm-xgmii-phy.h" 51 | 52 | #ifdef HAVE_VERILOG_VERILATOR 53 | #include 54 | #include "Vlmac3_wrapper_top.h" 55 | #include "verilated.h" 56 | #endif 57 | 58 | #define NR_MASTERS 3 59 | #define NR_DEVICES 4 60 | 61 | #ifndef BASE_ADDR 62 | #define BASE_ADDR 0xa0000000ULL 63 | #endif 64 | 65 | SC_MODULE(Top) 66 | { 67 | SC_HAS_PROCESS(Top); 68 | iconnect *bus; 69 | xilinx_zynqmp zynq; 70 | 71 | axidma_mm2s dma_mm2s_A; 72 | axidma_s2mm dma_s2mm_C; 73 | 74 | tlm2axis_bridge<256> tlm2axis; 75 | axis2tlm_bridge<256> axis2tlm; 76 | 77 | sc_signal rst, rst_n; 78 | 79 | sc_clock *clk; 80 | 81 | tlm2apb_bridge *tlm2apb_lmac; 82 | 83 | Vlmac3_wrapper_top *lmac; 84 | tlm_xgmii_phy phy; 85 | 86 | sc_signal > phy_txd; 87 | sc_signal > phy_txc; 88 | sc_signal > phy_rxd; 89 | sc_signal > phy_rxc; 90 | 91 | sc_signal > tx_axis_mac_tdata; 92 | sc_signal > tx_axis_mac_tstrb; 93 | sc_signal tx_axis_mac_tvalid; 94 | sc_signal tx_axis_mac_tlast; 95 | sc_signal tx_axis_mac_tuser; 96 | sc_signal tx_axis_mac_tready; 97 | 98 | sc_signal > rx_axis_mac_tdata; 99 | sc_signal > rx_axis_mac_tstrb; 100 | sc_signal rx_axis_mac_tvalid; 101 | sc_signal rx_axis_mac_tlast; 102 | sc_signal rx_axis_mac_tuser; 103 | sc_signal rx_axis_mac_tready; 104 | 105 | sc_signal apbsig_lmac_psel; 106 | sc_signal apbsig_lmac_penable; 107 | sc_signal apbsig_lmac_pwrite; 108 | sc_signal apbsig_lmac_pready; 109 | sc_signal > apbsig_lmac_paddr; 110 | sc_signal > apbsig_lmac_pwdata; 111 | sc_signal > apbsig_lmac_prdata; 112 | 113 | sc_signal apbsig_timer_psel; 114 | sc_signal apbsig_timer_penable; 115 | sc_signal apbsig_timer_pwrite; 116 | sc_signal apbsig_timer_pready; 117 | sc_signal > apbsig_timer_paddr; 118 | sc_signal > apbsig_timer_pwdata; 119 | sc_signal > apbsig_timer_prdata; 120 | 121 | void gen_rst_n(void) 122 | { 123 | rst_n.write(!rst.read()); 124 | } 125 | 126 | Top(sc_module_name name, const char *sk_descr, sc_time quantum) : 127 | zynq("zynq", sk_descr, remoteport_tlm_sync_untimed_ptr, false), 128 | dma_mm2s_A("dma_mm2s_A"), 129 | dma_s2mm_C("dma_s2mm_C"), 130 | tlm2axis("tlm2axis"), 131 | axis2tlm("axis2tlm"), 132 | rst("rst"), 133 | rst_n("rst_n"), 134 | 135 | phy("phy"), 136 | phy_txd("phy_txd"), 137 | phy_txc("phy_txc"), 138 | phy_rxd("phy_rxd"), 139 | phy_rxc("phy_rxc"), 140 | 141 | tx_axis_mac_tdata("tx_axis_mac_tdata"), 142 | tx_axis_mac_tstrb("tx_axis_mac_tstrb"), 143 | tx_axis_mac_tvalid("tx_axis_mac_tvalid"), 144 | tx_axis_mac_tlast("tx_axis_mac_tlast"), 145 | tx_axis_mac_tuser("tx_axis_mac_tuser"), 146 | tx_axis_mac_tready("tx_axis_mac_tready"), 147 | 148 | rx_axis_mac_tdata("rx_axis_mac_tdata"), 149 | rx_axis_mac_tstrb("rx_axis_mac_tstrb"), 150 | rx_axis_mac_tvalid("rx_axis_mac_tvalid"), 151 | rx_axis_mac_tlast("rx_axis_mac_tlast"), 152 | rx_axis_mac_tuser("rx_axis_mac_tuser"), 153 | rx_axis_mac_tready("rx_axis_mac_tready"), 154 | 155 | apbsig_lmac_psel("apblmac_psel"), 156 | apbsig_lmac_penable("apblmac_penable"), 157 | apbsig_lmac_pwrite("apblmac_pwrite"), 158 | apbsig_lmac_pready("apblmac_pready"), 159 | apbsig_lmac_paddr("apblmac_paddr"), 160 | apbsig_lmac_pwdata("apblmac_pwdata"), 161 | apbsig_lmac_prdata("apblmac_prdata"), 162 | 163 | apbsig_timer_psel("apbtimer_psel"), 164 | apbsig_timer_penable("apbtimer_penable"), 165 | apbsig_timer_pwrite("apbtimer_pwrite"), 166 | apbsig_timer_pready("apbtimer_pready"), 167 | apbsig_timer_paddr("apbtimer_paddr"), 168 | apbsig_timer_pwdata("apbtimer_pwdata"), 169 | apbsig_timer_prdata("apbtimer_prdata") 170 | { 171 | unsigned int i; 172 | 173 | SC_METHOD(gen_rst_n); 174 | sensitive << rst; 175 | 176 | m_qk.set_global_quantum(quantum); 177 | 178 | zynq.rst(rst); 179 | 180 | bus = new iconnect ("bus"); 181 | 182 | tlm2apb_lmac = new tlm2apb_bridge ("tlm2apb-lmac-bridge"); 183 | bus->memmap(BASE_ADDR + 0x30000ULL, 0x4000 - 1, 184 | ADDRMODE_RELATIVE, -1, tlm2apb_lmac->tgt_socket); 185 | 186 | bus->memmap(BASE_ADDR + 0x34000ULL, 0x100 - 1, 187 | ADDRMODE_RELATIVE, -1, dma_mm2s_A.tgt_socket); 188 | bus->memmap(BASE_ADDR + 0x35000ULL, 0x100 - 1, 189 | ADDRMODE_RELATIVE, -1, dma_s2mm_C.tgt_socket); 190 | 191 | bus->memmap(0x0LL, 0xffffffff - 1, 192 | ADDRMODE_RELATIVE, -1, *(zynq.s_axi_hpc_fpd[0])); 193 | 194 | zynq.s_axi_hpm_fpd[0]->bind(*(bus->t_sk[0])); 195 | 196 | dma_mm2s_A.init_socket.bind(*(bus->t_sk[1])); 197 | dma_s2mm_C.init_socket.bind(*(bus->t_sk[2])); 198 | 199 | dma_mm2s_A.stream_socket.bind(tlm2axis.tgt_socket); 200 | axis2tlm.socket.bind(dma_s2mm_C.stream_socket); 201 | 202 | dma_mm2s_A.irq(zynq.pl2ps_irq[2]); 203 | dma_s2mm_C.irq(zynq.pl2ps_irq[4]); 204 | 205 | /* Slow clock to keep simulation fast. */ 206 | clk = new sc_clock("clk", sc_time(10, SC_US)); 207 | lmac = new Vlmac3_wrapper_top("lmac"); 208 | 209 | tlm2axis.clk(*clk); 210 | tlm2axis.resetn(rst_n); 211 | tlm2axis.tvalid(tx_axis_mac_tvalid); 212 | tlm2axis.tready(tx_axis_mac_tready); 213 | tlm2axis.tdata(tx_axis_mac_tdata); 214 | tlm2axis.tstrb(tx_axis_mac_tstrb); 215 | tlm2axis.tuser(tx_axis_mac_tuser); 216 | tlm2axis.tlast(tx_axis_mac_tlast); 217 | 218 | axis2tlm.clk(*clk); 219 | axis2tlm.resetn(rst_n); 220 | axis2tlm.tvalid(rx_axis_mac_tvalid); 221 | axis2tlm.tready(rx_axis_mac_tready); 222 | axis2tlm.tdata(rx_axis_mac_tdata); 223 | axis2tlm.tstrb(rx_axis_mac_tstrb); 224 | axis2tlm.tuser(rx_axis_mac_tuser); 225 | axis2tlm.tlast(rx_axis_mac_tlast); 226 | 227 | lmac->clk(*clk); 228 | lmac->rst_n(rst_n); 229 | lmac->xgmii_txd(phy_txd); 230 | lmac->xgmii_txc(phy_txc); 231 | lmac->xgmii_rxd(phy_rxd); 232 | lmac->xgmii_rxc(phy_rxc); 233 | lmac->host_addr_reg(apbsig_lmac_paddr); 234 | lmac->reg_rd_start(apbsig_lmac_psel); 235 | lmac->reg_rd_done_out(apbsig_lmac_pready); 236 | lmac->FMAC_REGDOUT(apbsig_lmac_prdata); 237 | 238 | lmac->tx_axis_mac_tdata(tx_axis_mac_tdata); 239 | lmac->tx_axis_mac_tvalid(tx_axis_mac_tvalid); 240 | lmac->tx_axis_mac_tlast(tx_axis_mac_tlast); 241 | lmac->tx_axis_mac_tuser(tx_axis_mac_tuser); 242 | lmac->tx_axis_mac_tready(tx_axis_mac_tready); 243 | lmac->tx_axis_mac_tstrb(tx_axis_mac_tstrb); 244 | 245 | lmac->rx_axis_mac_tdata(rx_axis_mac_tdata); 246 | lmac->rx_axis_mac_tvalid(rx_axis_mac_tvalid); 247 | lmac->rx_axis_mac_tlast(rx_axis_mac_tlast); 248 | lmac->rx_axis_mac_tuser(rx_axis_mac_tuser); 249 | lmac->rx_axis_mac_tready(rx_axis_mac_tready); 250 | lmac->rx_axis_mac_tstrb(rx_axis_mac_tstrb); 251 | 252 | phy.tx.clk(*clk); 253 | phy.tx.xxd(phy_txd); 254 | phy.tx.xxc(phy_txc); 255 | 256 | phy.rx.clk(*clk); 257 | phy.rx.xxd(phy_rxd); 258 | phy.rx.xxc(phy_rxc); 259 | 260 | zynq.user_master[0]->bind(phy.rx.tgt_socket); 261 | phy.tx.init_socket.bind(*zynq.user_slave[0]); 262 | 263 | tlm2apb_lmac->clk(*clk); 264 | tlm2apb_lmac->psel(apbsig_lmac_psel); 265 | tlm2apb_lmac->penable(apbsig_lmac_penable); 266 | tlm2apb_lmac->pwrite(apbsig_lmac_pwrite); 267 | tlm2apb_lmac->paddr(apbsig_lmac_paddr); 268 | tlm2apb_lmac->pwdata(apbsig_lmac_pwdata); 269 | tlm2apb_lmac->prdata(apbsig_lmac_prdata); 270 | tlm2apb_lmac->pready(apbsig_lmac_pready); 271 | 272 | zynq.tie_off(); 273 | } 274 | 275 | private: 276 | tlm_utils::tlm_quantumkeeper m_qk; 277 | }; 278 | 279 | void usage(void) 280 | { 281 | cout << "tlm socket-path sync-quantum-ns" << endl; 282 | } 283 | 284 | int sc_main(int argc, char* argv[]) 285 | { 286 | Top *top; 287 | uint64_t sync_quantum; 288 | sc_trace_file *trace_fp = NULL; 289 | 290 | #if HAVE_VERILOG_VERILATOR 291 | Verilated::commandArgs(argc, argv); 292 | #endif 293 | 294 | if (argc < 3) { 295 | sync_quantum = 10000; 296 | } else { 297 | sync_quantum = strtoull(argv[2], NULL, 10); 298 | } 299 | 300 | sc_set_time_resolution(1, SC_PS); 301 | 302 | top = new Top("top", argv[1], sc_time((double) sync_quantum, SC_NS)); 303 | 304 | if (argc < 3) { 305 | sc_start(1, SC_PS); 306 | sc_stop(); 307 | usage(); 308 | exit(EXIT_FAILURE); 309 | } 310 | 311 | trace_fp = sc_create_vcd_trace_file("trace"); 312 | trace(trace_fp, *top, top->name()); 313 | 314 | #if VM_TRACE 315 | Verilated::traceEverOn(true); 316 | // If verilator was invoked with --trace argument, 317 | // and if at run time passed the +trace argument, turn on tracing 318 | VerilatedVcdSc* tfp = NULL; 319 | const char* flag = Verilated::commandArgsPlusMatch("trace"); 320 | if (flag && 0 == strcmp(flag, "+trace")) { 321 | tfp = new VerilatedVcdSc; 322 | top->lmac->trace(tfp, 99); 323 | tfp->open("vlt_dump.vcd"); 324 | } 325 | #endif 326 | 327 | /* Pull the reset signal. */ 328 | top->rst.write(true); 329 | sc_start(1, SC_US); 330 | top->rst.write(false); 331 | 332 | sc_start(); 333 | if (trace_fp) { 334 | sc_close_vcd_trace_file(trace_fp); 335 | } 336 | 337 | #if VM_TRACE 338 | if (tfp) { tfp->close(); tfp = NULL; } 339 | #endif 340 | return 0; 341 | } 342 | --------------------------------------------------------------------------------