Compare commits
10 Commits
379bf1f689
...
master
Author | SHA1 | Date | |
---|---|---|---|
84695d44b4 | |||
da27f38f0f | |||
646440493f | |||
78205b90f2 | |||
1e8986f8a7 | |||
346de9cdd4 | |||
8f03d29894 | |||
e18a0c1762 | |||
15d7e8b801 | |||
7c5351b9c3 |
@ -8,6 +8,9 @@ Remotesyn is a tool which proves a general abstraction for HDL/FPGA toolchains s
|
||||
+ Xilinx VIVADO synthesis and bitstream generation [`VIVADO`]
|
||||
+ Xilinx Vivado IP core generation [`VIVADO-IP`]
|
||||
+ Xilinx xsim (Vivado) simulation (pre and post synthesis) [`xsim`]
|
||||
+ Makefile build [`make`]
|
||||
+ QEMU simulation (nographic mode) [`qemu`]
|
||||
+ QuestaSim simulation [`questa`]
|
||||
|
||||
The HDL project is configured with a config file (in ini format) and should provide execution targets specified by a `[target.<target_name>]` tag with a toolchain setting (see the example directory for examples).
|
||||
|
||||
|
2
examples/GW1NSR-4C/.gitignore
vendored
Normal file
2
examples/GW1NSR-4C/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
OUT
|
||||
BUILD
|
8
examples/GW1NSR-4C/CON/io.cst
Normal file
8
examples/GW1NSR-4C/CON/io.cst
Normal file
@ -0,0 +1,8 @@
|
||||
IO_LOC "led_o" 10;
|
||||
IO_PORT "led_o" PULL_MODE=NONE DRIVE=8;
|
||||
|
||||
IO_LOC "reset_n_i" 15;
|
||||
IO_PORT "reset_n_i" PULL_MODE=UP;
|
||||
|
||||
IO_LOC "clk_i" 45;
|
||||
IO_PORT "clk_i" PULL_MODE=UP;
|
1
examples/GW1NSR-4C/CON/io.sdc
Normal file
1
examples/GW1NSR-4C/CON/io.sdc
Normal file
@ -0,0 +1 @@
|
||||
create_clock -name CLK_IN -period 37.037 -waveform {0 18.52} [get_ports {clk_i}]
|
23
examples/GW1NSR-4C/RTL/toplevel.v
Normal file
23
examples/GW1NSR-4C/RTL/toplevel.v
Normal file
@ -0,0 +1,23 @@
|
||||
module led_blink
|
||||
(
|
||||
input clk_i,
|
||||
input reset_n_i,
|
||||
output led_o
|
||||
);
|
||||
|
||||
reg [23:0] counter;
|
||||
reg polarity;
|
||||
|
||||
always@(posedge clk_i) begin
|
||||
if (!reset_n_i)
|
||||
counter <= 24'h00000;
|
||||
else
|
||||
counter <= counter + 1'b1;
|
||||
|
||||
if (counter == 24'hFFFFF)
|
||||
polarity <= ~polarity;
|
||||
end
|
||||
|
||||
assign led_o = polarity;
|
||||
|
||||
endmodule
|
28
examples/GW1NSR-4C/project.cfg
Normal file
28
examples/GW1NSR-4C/project.cfg
Normal file
@ -0,0 +1,28 @@
|
||||
[project]
|
||||
name = gowin_project
|
||||
version = 0.1
|
||||
out_dir = OUT
|
||||
build_dir = BUILD
|
||||
|
||||
[server]
|
||||
hostname = localhost
|
||||
port = 2020
|
||||
privkey = /home/joppe/.ssh/id_rsa
|
||||
pubkey = /home/joppe/.ssh/id_rsa.pub
|
||||
|
||||
# ######################################
|
||||
# Basic synthesis
|
||||
[target.synth]
|
||||
toolchain = gowin
|
||||
|
||||
# Toolchain settings
|
||||
family = GW1NSR-4C
|
||||
device = GW1NSR-LV4CQN48PC6/I5
|
||||
toplevel = led_blink
|
||||
|
||||
# Fileset
|
||||
# files_vhdl =
|
||||
files_verilog = RTL/toplevel.v
|
||||
files_con = CON/io.cst
|
||||
CON/io.sdc
|
||||
# ######################################
|
19
examples/zynq7000/README.md
Normal file
19
examples/zynq7000/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# ZYNQ 7 series project
|
||||
|
||||
### Basic FPGA workflow
|
||||
+ target `ip`: Generate IP blocks defined in the tcl files in the IP directory
|
||||
+ target `synth`: Synthesize design
|
||||
+ target `sim`: Behavioural simulation of part of the design
|
||||
+ target `psim`: Post synthesis simulation of mentioned part of the design
|
||||
|
||||
### ZYNQ SoC workflos
|
||||
+ target `firmware`: Compile the firmware running on the ARM core(s) with the `make` toolchain
|
||||
+ target `firmsim`: Simulate the firmware with QEMU without PS/PL cosimulation with the `qemu` toolchain
|
||||
+ target `devtree`: Compile the device tree for a PS/PL cosimulation with QEMU
|
||||
+ target `cosim_ps`: PS part of the cosimulation. Must be ran first
|
||||
+ target `cosim_pl`: PL part of the cosimulation. Must be ran in a separate terminal while the PS part is still running
|
||||
|
||||
### Notes:
|
||||
Compilation with Xilinx provided gcc and binutils done with `xsc` can be problematic... This is the reason
|
||||
Questasim is used for the cosimulation. If one would use the free Intel variant of Questasim post synthesis
|
||||
simulation will not be possible. The attempt to get DPI-C working with xsim is not stopped!
|
186
examples/zynq7000/SIM/c/cosim.c
Normal file
186
examples/zynq7000/SIM/c/cosim.c
Normal file
@ -0,0 +1,186 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "remote-port-proto.h"
|
||||
#define UNIX_PREFIX "unix:"
|
||||
|
||||
int fd;
|
||||
uint8_t buf[4096];
|
||||
struct rp_pkt_hdr * hdr = (struct rp_pkt_hdr*)buf;
|
||||
struct rp_pkt * payload = (struct rp_pkt*)(buf);
|
||||
int rp_pkt_id = 0;
|
||||
struct rp_peer_state state;
|
||||
size_t pkt_size;
|
||||
FILE * log;
|
||||
|
||||
int still_to_write, still_to_read, datpointer;
|
||||
uint32_t write_addr, read_addr;
|
||||
|
||||
int start_cosim(char * descr){
|
||||
// Open socket
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
// Try to connect
|
||||
struct sockaddr_un addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, descr + strlen(UNIX_PREFIX), sizeof addr.sun_path);
|
||||
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) >= 0){
|
||||
// log = fopen("cosim_log.txt", "w");
|
||||
return 0;
|
||||
}else{
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void end_cosim(){
|
||||
close(fd);
|
||||
// fclose(log);
|
||||
}
|
||||
|
||||
int wait_cosim(uint32_t * retaddr, uint32_t * time){
|
||||
// fprintf(log, "-->");
|
||||
if(still_to_write){
|
||||
*retaddr = write_addr;
|
||||
// fprintf(log, "\r\nwrite [%08x] @ %d\r\n", *retaddr, *time);
|
||||
return 1;
|
||||
}else if(still_to_read){
|
||||
*retaddr = read_addr;
|
||||
// fprintf(log, "\r\nread [%08x] @ %d\r\n", *retaddr, *time);
|
||||
return 2;
|
||||
}else{
|
||||
int n;
|
||||
int retval = 0;
|
||||
// Receive header
|
||||
do{
|
||||
n = recv(fd, hdr, sizeof(struct rp_pkt_hdr), 0);
|
||||
} while(n<=0);
|
||||
rp_decode_hdr(hdr);
|
||||
|
||||
// fprintf(log, " . ");
|
||||
|
||||
// Receive payload
|
||||
if(hdr->len){
|
||||
do{
|
||||
n = recv(fd, hdr+1, hdr->len, 0);
|
||||
} while(n<=0);
|
||||
}
|
||||
rp_decode_payload(payload);
|
||||
|
||||
// fprintf(log, "%d\r\n", hdr->cmd);
|
||||
switch(hdr->cmd){
|
||||
|
||||
case RP_CMD_hello:{
|
||||
rp_process_caps(&state, buf+payload->hello.caps.offset, payload->hello.caps.len);
|
||||
|
||||
// Send HELO packet
|
||||
uint32_t caps[] = {
|
||||
CAP_BUSACCESS_EXT_BASE
|
||||
};
|
||||
size_t s = rp_encode_hello_caps(rp_pkt_id++, 0, buf, 4, 3, caps, caps, sizeof(caps)/sizeof(uint32_t));
|
||||
send(fd, buf, s, 0);
|
||||
send(fd, caps, sizeof(caps), 0);
|
||||
// fprintf(log, "hello\r\n");
|
||||
} break;
|
||||
|
||||
case RP_CMD_interrupt:{
|
||||
*time = (uint32_t) payload->interrupt.timestamp;
|
||||
// fprintf(log, "interrupt @ %ld\r\n", payload->interrupt.timestamp);
|
||||
} break;
|
||||
|
||||
case RP_CMD_write:{
|
||||
int addr = payload->busaccess_ext_base.addr;
|
||||
int len = payload->busaccess_ext_base.len;
|
||||
uint64_t t = payload->busaccess_ext_base.timestamp;
|
||||
|
||||
if(len/4>1){
|
||||
// Must be more than one write cycle
|
||||
still_to_write = len/4-1;
|
||||
write_addr = addr+4;
|
||||
datpointer = 0;
|
||||
}else{
|
||||
still_to_write = 0;
|
||||
}
|
||||
|
||||
retval = 1;
|
||||
*retaddr = addr;
|
||||
*time = (uint32_t)t;
|
||||
// fprintf(log, "write [%08x] @ %d\r\n", *retaddr, *time);
|
||||
|
||||
// Respond to write
|
||||
struct rp_encode_busaccess_in in = {0};
|
||||
rp_encode_busaccess_in_rsp_init(&in, payload);
|
||||
pkt_size = rp_encode_busaccess(&state, buf, &in);
|
||||
} break;
|
||||
|
||||
case RP_CMD_read:{
|
||||
int len = payload->busaccess_ext_base.len;
|
||||
int addr = payload->busaccess_ext_base.addr;
|
||||
uint64_t t = payload->busaccess_ext_base.timestamp;
|
||||
|
||||
if(len/4>1){
|
||||
// Must be more than one write cycle
|
||||
still_to_read = len/4-1;
|
||||
read_addr = addr+4;
|
||||
datpointer = 0;
|
||||
}else{
|
||||
still_to_read = 0;
|
||||
}
|
||||
|
||||
retval = 2;
|
||||
*retaddr = addr;
|
||||
*time = (uint32_t)t;
|
||||
// fprintf(log, "read [%08x] @ %d\r\n", *retaddr, *time);
|
||||
|
||||
// Respond to read
|
||||
struct rp_encode_busaccess_in in = {0};
|
||||
rp_encode_busaccess_in_rsp_init(&in, payload);
|
||||
pkt_size = rp_encode_busaccess(&state, buf, &in);
|
||||
} break;
|
||||
|
||||
case RP_CMD_sync:{
|
||||
// Respond to sync
|
||||
struct rp_pkt resp = {0};
|
||||
size_t s = rp_encode_sync_resp(rp_pkt_id++, 0, &resp, payload->sync.timestamp);
|
||||
uint64_t t = payload->sync.timestamp;
|
||||
*time = (uint32_t)t;
|
||||
send(fd, &resp, s, 0);
|
||||
// fprintf(log, "SYNC @ %ld\r\n", payload->sync.timestamp);
|
||||
} break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
void read_cosim(unsigned int value){
|
||||
unsigned int * dat = (unsigned int*)((void*)payload + sizeof(payload->busaccess_ext_base));
|
||||
dat[datpointer] = value;
|
||||
// fprintf(log, " -> %08x\r\n", value);
|
||||
}
|
||||
|
||||
int write_cosim(){
|
||||
unsigned int * dat = (unsigned int*)((void*)payload + sizeof(payload->busaccess_ext_base));
|
||||
fprintf(log, " -> %08x\r\n", dat[datpointer]);
|
||||
// return dat[datpointer];
|
||||
}
|
||||
|
||||
void finalize_cosim(uint32_t timestamp){
|
||||
if(still_to_write){
|
||||
still_to_write--;
|
||||
write_addr += 4;
|
||||
datpointer++;
|
||||
}else if(still_to_read){
|
||||
still_to_read--;
|
||||
read_addr += 4;
|
||||
datpointer++;
|
||||
}else{
|
||||
payload->busaccess_ext_base.timestamp = (uint64_t) timestamp;
|
||||
send(fd, buf, pkt_size, 0);
|
||||
}
|
||||
// fprintf(log, "finalize @ %d\r\n<--\r\n", timestamp);
|
||||
}
|
513
examples/zynq7000/SIM/c/remote-port-proto.c
Normal file
513
examples/zynq7000/SIM/c/remote-port-proto.c
Normal file
@ -0,0 +1,513 @@
|
||||
/*
|
||||
* Remote-port protocol
|
||||
*
|
||||
* Copyright (c) 2013 Xilinx Inc
|
||||
* Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
# define _DEFAULT_SOURCE
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include "remote-port-proto.h"
|
||||
|
||||
#undef MIN
|
||||
#define MIN(x, y) (x < y ? x : y)
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <endian.h>
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
# include <sys/endian.h>
|
||||
#elif defined(__OpenBSD__)
|
||||
# include <sys/types.h>
|
||||
# define be16toh(x) betoh16(x)
|
||||
# define be32toh(x) betoh32(x)
|
||||
# define be64toh(x) betoh64(x)
|
||||
#elif defined(__WIN32)
|
||||
/* We assume little endian. */
|
||||
# define htobe64(x) _byteswap_uint64(x)
|
||||
# define htobe32(x) _byteswap_ulong(x)
|
||||
# define htobe16(x) _byteswap_ushort(x)
|
||||
|
||||
# define be64toh(x) _byteswap_uint64(x)
|
||||
# define be32toh(x) _byteswap_ulong(x)
|
||||
# define be16toh(x) _byteswap_ushort(x)
|
||||
#endif
|
||||
|
||||
/* Fallback for ancient Linux systems. */
|
||||
#ifndef htobe64
|
||||
# include <byteswap.h>
|
||||
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define htobe64(x) bswap_64(x)
|
||||
# define htobe32(x) bswap_32(x)
|
||||
# define htobe16(x) bswap_16(x)
|
||||
|
||||
# define be64toh(x) bswap_64(x)
|
||||
# define be32toh(x) bswap_32(x)
|
||||
# define be16toh(x) bswap_16(x)
|
||||
# else
|
||||
# define htobe64(x) x
|
||||
# define htobe32(x) x
|
||||
# define htobe16(x) x
|
||||
|
||||
# define be64toh(x) x
|
||||
# define be32toh(x) x
|
||||
# define be16toh(x) x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static const char *rp_cmd_names[RP_CMD_max + 1] = {
|
||||
[RP_CMD_nop] = "nop",
|
||||
[RP_CMD_hello] = "hello",
|
||||
[RP_CMD_cfg] = "cfg",
|
||||
[RP_CMD_read] = "read",
|
||||
[RP_CMD_write] = "write",
|
||||
[RP_CMD_interrupt] = "interrupt",
|
||||
[RP_CMD_sync] = "sync",
|
||||
[RP_CMD_ats_req] = "ats_request",
|
||||
[RP_CMD_ats_inv] = "ats_invalidation",
|
||||
};
|
||||
|
||||
const char *rp_cmd_to_string(enum rp_cmd cmd)
|
||||
{
|
||||
assert(cmd <= RP_CMD_max);
|
||||
return rp_cmd_names[cmd];
|
||||
}
|
||||
|
||||
int rp_decode_hdr(struct rp_pkt *pkt)
|
||||
{
|
||||
int used = 0;
|
||||
|
||||
pkt->hdr.cmd = be32toh(pkt->hdr.cmd);
|
||||
pkt->hdr.len = be32toh(pkt->hdr.len);
|
||||
pkt->hdr.id = be32toh(pkt->hdr.id);
|
||||
pkt->hdr.flags = be32toh(pkt->hdr.flags);
|
||||
pkt->hdr.dev = be32toh(pkt->hdr.dev);
|
||||
used += sizeof pkt->hdr;
|
||||
return used;
|
||||
}
|
||||
|
||||
int rp_decode_payload(struct rp_pkt *pkt)
|
||||
{
|
||||
int used = 0;
|
||||
/* Master_id has an odd decoding due to historical reasons. */
|
||||
uint64_t master_id;
|
||||
|
||||
switch (pkt->hdr.cmd) {
|
||||
case RP_CMD_hello:
|
||||
assert(pkt->hdr.len >= sizeof pkt->hello.version);
|
||||
pkt->hello.version.major = be16toh(pkt->hello.version.major);
|
||||
pkt->hello.version.minor = be16toh(pkt->hello.version.minor);
|
||||
used += sizeof pkt->hello.version;
|
||||
|
||||
if ((pkt->hdr.len - used) >= sizeof pkt->hello.caps) {
|
||||
void *offset;
|
||||
int i;
|
||||
|
||||
pkt->hello.caps.offset = be32toh(pkt->hello.caps.offset);
|
||||
pkt->hello.caps.len = be16toh(pkt->hello.caps.len);
|
||||
|
||||
offset = (char *)pkt + pkt->hello.caps.offset;
|
||||
for (i = 0; i < pkt->hello.caps.len; i++) {
|
||||
uint32_t cap;
|
||||
|
||||
/* We don't know if offset is 32bit aligned so use
|
||||
* memcpy to do the endian conversion. */
|
||||
memcpy(&cap, offset + i * sizeof cap, sizeof cap);
|
||||
cap = be32toh(cap);
|
||||
memcpy(offset + i * sizeof cap, &cap, sizeof cap);
|
||||
}
|
||||
used += sizeof pkt->hello.caps;
|
||||
} else {
|
||||
pkt->hello.caps.offset = 0;
|
||||
pkt->hello.caps.len = 0;
|
||||
}
|
||||
|
||||
/* Consume everything ignoring additional headers we do not yet
|
||||
* know about. */
|
||||
used = pkt->hdr.len;
|
||||
break;
|
||||
case RP_CMD_write:
|
||||
case RP_CMD_read:
|
||||
assert(pkt->hdr.len >= sizeof pkt->busaccess - sizeof pkt->hdr);
|
||||
pkt->busaccess.timestamp = be64toh(pkt->busaccess.timestamp);
|
||||
pkt->busaccess.addr = be64toh(pkt->busaccess.addr);
|
||||
pkt->busaccess.master_id = be16toh(pkt->busaccess.master_id);
|
||||
pkt->busaccess.attributes = be64toh(pkt->busaccess.attributes);
|
||||
pkt->busaccess.len = be32toh(pkt->busaccess.len);
|
||||
pkt->busaccess.width = be32toh(pkt->busaccess.width);
|
||||
pkt->busaccess.stream_width = be32toh(pkt->busaccess.stream_width);
|
||||
master_id = be16toh(pkt->busaccess.master_id);
|
||||
|
||||
used += sizeof pkt->busaccess - sizeof pkt->hdr;
|
||||
|
||||
if (pkt->busaccess.attributes & RP_BUS_ATTR_EXT_BASE) {
|
||||
struct rp_pkt_busaccess_ext_base *pext = &pkt->busaccess_ext_base;
|
||||
|
||||
assert(pkt->hdr.len >= sizeof *pext - sizeof pkt->hdr);
|
||||
master_id |= (uint64_t)be16toh(pext->master_id_31_16) << 16;
|
||||
master_id |= (uint64_t)be32toh(pext->master_id_63_32) << 32;
|
||||
pext->data_offset = be32toh(pext->data_offset);
|
||||
pext->next_offset = be32toh(pext->next_offset);
|
||||
pext->byte_enable_offset = be32toh(pext->byte_enable_offset);
|
||||
pext->byte_enable_len = be32toh(pext->byte_enable_len);
|
||||
|
||||
used += sizeof *pext - sizeof pkt->busaccess;
|
||||
}
|
||||
pkt->busaccess.master_id = master_id;
|
||||
break;
|
||||
case RP_CMD_interrupt:
|
||||
pkt->interrupt.timestamp = be64toh(pkt->interrupt.timestamp);
|
||||
pkt->interrupt.vector = be64toh(pkt->interrupt.vector);
|
||||
pkt->interrupt.line = be32toh(pkt->interrupt.line);
|
||||
pkt->interrupt.val = pkt->interrupt.val;
|
||||
used += pkt->hdr.len;
|
||||
break;
|
||||
case RP_CMD_sync:
|
||||
pkt->sync.timestamp = be64toh(pkt->interrupt.timestamp);
|
||||
used += pkt->hdr.len;
|
||||
break;
|
||||
case RP_CMD_ats_req:
|
||||
case RP_CMD_ats_inv:
|
||||
pkt->ats.attributes = be64toh(pkt->ats.attributes);
|
||||
pkt->ats.addr = be64toh(pkt->ats.addr);
|
||||
pkt->ats.len = be64toh(pkt->ats.len);
|
||||
pkt->ats.result = be32toh(pkt->ats.result);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
void rp_encode_hdr(struct rp_pkt_hdr *hdr, uint32_t cmd, uint32_t id,
|
||||
uint32_t dev, uint32_t len, uint32_t flags)
|
||||
{
|
||||
hdr->cmd = htobe32(cmd);
|
||||
hdr->len = htobe32(len);
|
||||
hdr->id = htobe32(id);
|
||||
hdr->dev = htobe32(dev);
|
||||
hdr->flags = htobe32(flags);
|
||||
}
|
||||
|
||||
size_t rp_encode_hello_caps(uint32_t id, uint32_t dev, struct rp_pkt_hello *pkt,
|
||||
uint16_t version_major, uint16_t version_minor,
|
||||
uint32_t *caps, uint32_t *caps_out,
|
||||
uint32_t caps_len)
|
||||
{
|
||||
size_t psize = sizeof *pkt + sizeof caps[0] * caps_len;
|
||||
unsigned int i;
|
||||
|
||||
rp_encode_hdr(&pkt->hdr, RP_CMD_hello, id, dev,
|
||||
psize - sizeof pkt->hdr, 0);
|
||||
pkt->version.major = htobe16(version_major);
|
||||
pkt->version.minor = htobe16(version_minor);
|
||||
|
||||
/* Feature list is appeneded right after the hello packet. */
|
||||
pkt->caps.offset = htobe32(sizeof *pkt);
|
||||
pkt->caps.len = htobe16(caps_len);
|
||||
|
||||
for (i = 0; i < caps_len; i++) {
|
||||
uint32_t cap;
|
||||
|
||||
cap = caps[i];
|
||||
caps_out[i] = htobe32(cap);
|
||||
}
|
||||
return sizeof *pkt;
|
||||
}
|
||||
|
||||
static void rp_encode_busaccess_common(struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width)
|
||||
{
|
||||
pkt->timestamp = htobe64(clk);
|
||||
pkt->master_id = htobe16(master_id);
|
||||
pkt->addr = htobe64(addr);
|
||||
pkt->attributes = htobe64(attr);
|
||||
pkt->len = htobe32(size);
|
||||
pkt->width = htobe32(width);
|
||||
pkt->stream_width = htobe32(stream_width);
|
||||
}
|
||||
|
||||
size_t rp_encode_read(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width)
|
||||
{
|
||||
rp_encode_hdr(&pkt->hdr, RP_CMD_read, id, dev,
|
||||
sizeof *pkt - sizeof pkt->hdr, 0);
|
||||
rp_encode_busaccess_common(pkt, clk, master_id, addr, attr,
|
||||
size, width, stream_width);
|
||||
return sizeof *pkt;
|
||||
}
|
||||
|
||||
size_t rp_encode_read_resp(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width)
|
||||
{
|
||||
rp_encode_hdr(&pkt->hdr, RP_CMD_read, id, dev,
|
||||
sizeof *pkt - sizeof pkt->hdr + size, RP_PKT_FLAGS_response);
|
||||
rp_encode_busaccess_common(pkt, clk, master_id, addr, attr,
|
||||
size, width, stream_width);
|
||||
return sizeof *pkt + size;
|
||||
}
|
||||
|
||||
size_t rp_encode_write(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width)
|
||||
{
|
||||
rp_encode_hdr(&pkt->hdr, RP_CMD_write, id, dev,
|
||||
sizeof *pkt - sizeof pkt->hdr + size, 0);
|
||||
rp_encode_busaccess_common(pkt, clk, master_id, addr, attr,
|
||||
size, width, stream_width);
|
||||
return sizeof *pkt;
|
||||
}
|
||||
|
||||
size_t rp_encode_write_resp(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width)
|
||||
{
|
||||
rp_encode_hdr(&pkt->hdr, RP_CMD_write, id, dev,
|
||||
sizeof *pkt - sizeof pkt->hdr, RP_PKT_FLAGS_response);
|
||||
rp_encode_busaccess_common(pkt, clk, master_id, addr, attr,
|
||||
size, width, stream_width);
|
||||
return sizeof *pkt;
|
||||
}
|
||||
|
||||
/* New API for extended header. */
|
||||
size_t rp_encode_busaccess(struct rp_peer_state *peer,
|
||||
struct rp_pkt_busaccess_ext_base *pkt,
|
||||
struct rp_encode_busaccess_in *in) {
|
||||
struct rp_pkt_busaccess *pkt_v4_0 = (void *) pkt;
|
||||
uint32_t hsize = 0;
|
||||
uint32_t ret_size = 0;
|
||||
|
||||
/* Allocate packet space. */
|
||||
if (in->cmd == RP_CMD_write && !(in->flags & RP_PKT_FLAGS_response)) {
|
||||
hsize = in->size;
|
||||
}
|
||||
if (in->cmd == RP_CMD_read && (in->flags & RP_PKT_FLAGS_response)) {
|
||||
hsize = in->size;
|
||||
ret_size = in->size;
|
||||
}
|
||||
|
||||
/* If peer does not support the busaccess base extensions, use the
|
||||
* old layout. For responses, what matters is if we're responding
|
||||
* to a packet with the extensions.
|
||||
*/
|
||||
if (!peer->caps.busaccess_ext_base && !(in->attr & RP_BUS_ATTR_EXT_BASE)) {
|
||||
/* Old layout. */
|
||||
assert(in->master_id < UINT16_MAX);
|
||||
|
||||
rp_encode_hdr(&pkt->hdr, in->cmd, in->id, in->dev,
|
||||
sizeof *pkt_v4_0 - sizeof pkt->hdr + hsize, in->flags);
|
||||
rp_encode_busaccess_common(pkt_v4_0, in->clk, in->master_id,
|
||||
in->addr, in->attr,
|
||||
in->size, in->width, in->stream_width);
|
||||
return sizeof *pkt_v4_0 + ret_size;
|
||||
}
|
||||
|
||||
/* Encode the extended fields. */
|
||||
pkt->master_id_31_16 = htobe16(in->master_id >> 16);
|
||||
pkt->master_id_63_32 = htobe32(in->master_id >> 32);
|
||||
|
||||
/* We always put data right after the header. */
|
||||
pkt->data_offset = htobe32(sizeof *pkt);
|
||||
pkt->next_offset = 0;
|
||||
|
||||
pkt->byte_enable_offset = htobe32(sizeof *pkt + hsize);
|
||||
pkt->byte_enable_len = htobe32(in->byte_enable_len);
|
||||
hsize += in->byte_enable_len;
|
||||
|
||||
rp_encode_hdr(&pkt->hdr, in->cmd, in->id, in->dev,
|
||||
sizeof *pkt - sizeof pkt->hdr + hsize, in->flags);
|
||||
rp_encode_busaccess_common(pkt_v4_0, in->clk, in->master_id, in->addr,
|
||||
in->attr | RP_BUS_ATTR_EXT_BASE,
|
||||
in->size, in->width, in->stream_width);
|
||||
|
||||
return sizeof *pkt + ret_size;
|
||||
}
|
||||
|
||||
size_t rp_encode_interrupt_f(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_interrupt *pkt,
|
||||
int64_t clk,
|
||||
uint32_t line, uint64_t vector, uint8_t val,
|
||||
uint32_t flags)
|
||||
{
|
||||
rp_encode_hdr(&pkt->hdr, RP_CMD_interrupt, id, dev,
|
||||
sizeof *pkt - sizeof pkt->hdr, flags);
|
||||
pkt->timestamp = htobe64(clk);
|
||||
pkt->vector = htobe64(vector);
|
||||
pkt->line = htobe32(line);
|
||||
pkt->val = val;
|
||||
return sizeof *pkt;
|
||||
}
|
||||
|
||||
size_t rp_encode_interrupt(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_interrupt *pkt,
|
||||
int64_t clk,
|
||||
uint32_t line, uint64_t vector, uint8_t val)
|
||||
{
|
||||
return rp_encode_interrupt_f(id, dev, pkt, clk, line, vector, val, 0);
|
||||
}
|
||||
|
||||
static size_t rp_encode_ats_common(uint32_t cmd, uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_ats *pkt,
|
||||
int64_t clk, uint64_t attr, uint64_t addr,
|
||||
uint64_t len, uint64_t result, uint32_t flags)
|
||||
{
|
||||
rp_encode_hdr(&pkt->hdr, cmd, id, dev,
|
||||
sizeof *pkt - sizeof pkt->hdr, flags);
|
||||
pkt->timestamp = htobe64(clk);
|
||||
pkt->attributes = htobe64(attr);
|
||||
pkt->addr = htobe64(addr);
|
||||
pkt->len = htobe64(len);
|
||||
pkt->result = htobe32(result);
|
||||
return sizeof *pkt;
|
||||
}
|
||||
|
||||
size_t rp_encode_ats_req(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_ats *pkt,
|
||||
int64_t clk, uint64_t attr, uint64_t addr,
|
||||
uint64_t len, uint64_t result, uint32_t flags)
|
||||
{
|
||||
return rp_encode_ats_common(RP_CMD_ats_req, id, dev,
|
||||
pkt, clk, attr,
|
||||
addr, len, result, flags);
|
||||
}
|
||||
|
||||
size_t rp_encode_ats_inv(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_ats *pkt,
|
||||
int64_t clk, uint64_t attr, uint64_t addr,
|
||||
uint64_t len, uint64_t result, uint32_t flags)
|
||||
{
|
||||
return rp_encode_ats_common(RP_CMD_ats_inv, id, dev,
|
||||
pkt, clk, attr,
|
||||
addr, len, result, flags);
|
||||
}
|
||||
|
||||
static size_t rp_encode_sync_common(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_sync *pkt,
|
||||
int64_t clk, uint32_t flags)
|
||||
{
|
||||
rp_encode_hdr(&pkt->hdr, RP_CMD_sync, id, dev,
|
||||
sizeof *pkt - sizeof pkt->hdr, flags);
|
||||
pkt->timestamp = htobe64(clk);
|
||||
return sizeof *pkt;
|
||||
}
|
||||
|
||||
size_t rp_encode_sync(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_sync *pkt,
|
||||
int64_t clk)
|
||||
{
|
||||
return rp_encode_sync_common(id, dev, pkt, clk, 0);
|
||||
}
|
||||
|
||||
size_t rp_encode_sync_resp(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_sync *pkt,
|
||||
int64_t clk)
|
||||
{
|
||||
return rp_encode_sync_common(id, dev, pkt, clk, RP_PKT_FLAGS_response);
|
||||
}
|
||||
|
||||
void rp_process_caps(struct rp_peer_state *peer,
|
||||
void *caps, size_t caps_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(peer->caps.busaccess_ext_base == false);
|
||||
|
||||
for (i = 0; i < caps_len; i++) {
|
||||
uint32_t cap;
|
||||
|
||||
memcpy(&cap, caps + i * sizeof cap, sizeof cap);
|
||||
|
||||
switch (cap) {
|
||||
case CAP_BUSACCESS_EXT_BASE:
|
||||
peer->caps.busaccess_ext_base = true;
|
||||
break;
|
||||
case CAP_BUSACCESS_EXT_BYTE_EN:
|
||||
peer->caps.busaccess_ext_byte_en = true;
|
||||
break;
|
||||
case CAP_WIRE_POSTED_UPDATES:
|
||||
peer->caps.wire_posted_updates = true;
|
||||
break;
|
||||
case CAP_ATS:
|
||||
peer->caps.ats = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rp_dpkt_alloc(RemotePortDynPkt *dpkt, size_t size)
|
||||
{
|
||||
if (dpkt->size < size) {
|
||||
char *u8;
|
||||
dpkt->pkt = realloc(dpkt->pkt, size);
|
||||
u8 = (void *) dpkt->pkt;
|
||||
memset(u8 + dpkt->size, 0, size - dpkt->size);
|
||||
dpkt->size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void rp_dpkt_swap(RemotePortDynPkt *a, RemotePortDynPkt *b)
|
||||
{
|
||||
struct rp_pkt *tmp_pkt;
|
||||
size_t tmp_size;
|
||||
|
||||
tmp_pkt = a->pkt;
|
||||
tmp_size = a->size;
|
||||
a->pkt = b->pkt;
|
||||
a->size = b->size;
|
||||
b->pkt = tmp_pkt;
|
||||
b->size = tmp_size;
|
||||
}
|
||||
|
||||
bool rp_dpkt_is_valid(RemotePortDynPkt *dpkt)
|
||||
{
|
||||
return dpkt->size > 0 && dpkt->pkt->hdr.len;
|
||||
}
|
||||
|
||||
void rp_dpkt_invalidate(RemotePortDynPkt *dpkt)
|
||||
{
|
||||
assert(rp_dpkt_is_valid(dpkt));
|
||||
dpkt->pkt->hdr.len = 0;
|
||||
}
|
||||
|
||||
inline void rp_dpkt_free(RemotePortDynPkt *dpkt)
|
||||
{
|
||||
dpkt->size = 0;
|
||||
free(dpkt->pkt);
|
||||
}
|
534
examples/zynq7000/SIM/c/remote-port-proto.h
Normal file
534
examples/zynq7000/SIM/c/remote-port-proto.h
Normal file
@ -0,0 +1,534 @@
|
||||
/*
|
||||
* QEMU remote port protocol parts.
|
||||
*
|
||||
* Copyright (c) 2013 Xilinx Inc
|
||||
* Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef REMOTE_PORT_PROTO_H__
|
||||
#define REMOTE_PORT_PROTO_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Remote-Port (RP) is an inter-simulator protocol. It assumes a reliable
|
||||
* point to point communcation with the remote simulation environment.
|
||||
*
|
||||
* Setup
|
||||
* In the SETUP phase a mandatory HELLO packet is exchanged with optional
|
||||
* CFG packets following. HELLO packets are useful to ensure that both
|
||||
* sides are speaking the same protocol and using compatible versions.
|
||||
*
|
||||
* CFG packets are used to negotiate configuration options. At the moment
|
||||
* these remain unimplemented.
|
||||
*
|
||||
* Once the session is up, communication can start through various other
|
||||
* commands. The list can be found further down this document.
|
||||
* Commands are carried over RP packets. Every RP packet contains a header
|
||||
* with length, flags and an ID to track potential responses.
|
||||
* The header is followed by a packet specific payload. You'll find the
|
||||
* details of the various commands packet layouts here. Some commands can
|
||||
* carry data/blobs in their payload.
|
||||
*/
|
||||
|
||||
|
||||
#define RP_VERSION_MAJOR 4
|
||||
#define RP_VERSION_MINOR 3
|
||||
|
||||
#if defined(_WIN32) && defined(__MINGW32__)
|
||||
/* mingw GCC has a bug with packed attributes. */
|
||||
#define PACKED __attribute__ ((gcc_struct, packed))
|
||||
#else
|
||||
#define PACKED __attribute__ ((packed))
|
||||
#endif
|
||||
|
||||
/* Could be auto generated. */
|
||||
enum rp_cmd {
|
||||
RP_CMD_nop = 0,
|
||||
RP_CMD_hello = 1,
|
||||
RP_CMD_cfg = 2,
|
||||
RP_CMD_read = 3,
|
||||
RP_CMD_write = 4,
|
||||
RP_CMD_interrupt = 5,
|
||||
RP_CMD_sync = 6,
|
||||
RP_CMD_ats_req = 7,
|
||||
RP_CMD_ats_inv = 8,
|
||||
RP_CMD_max = 8
|
||||
};
|
||||
|
||||
enum {
|
||||
RP_OPT_quantum = 0,
|
||||
};
|
||||
|
||||
struct rp_cfg_state {
|
||||
uint64_t quantum;
|
||||
};
|
||||
|
||||
enum {
|
||||
RP_PKT_FLAGS_optional = 1 << 0,
|
||||
RP_PKT_FLAGS_response = 1 << 1,
|
||||
|
||||
/* Posted hint.
|
||||
* When set this means that the receiver is not required to respond to
|
||||
* the message. Since it's just a hint, the sender must be prepared to
|
||||
* drop responses. Note that since flags are echoed back in responses
|
||||
* a response to a posted packet will be easy to identify early in the
|
||||
* protocol stack.
|
||||
*/
|
||||
RP_PKT_FLAGS_posted = 1 << 2,
|
||||
};
|
||||
|
||||
struct rp_pkt_hdr {
|
||||
uint32_t cmd;
|
||||
uint32_t len;
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
uint32_t dev;
|
||||
} PACKED;
|
||||
|
||||
struct rp_pkt_cfg {
|
||||
struct rp_pkt_hdr hdr;
|
||||
uint32_t opt;
|
||||
uint8_t set;
|
||||
} PACKED;
|
||||
|
||||
struct rp_version {
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
} PACKED;
|
||||
|
||||
struct rp_capabilities {
|
||||
/* Offset from start of packet. */
|
||||
uint32_t offset;
|
||||
uint16_t len;
|
||||
uint16_t reserved0;
|
||||
} PACKED;
|
||||
|
||||
enum {
|
||||
CAP_BUSACCESS_EXT_BASE = 1, /* New header layout. */
|
||||
CAP_BUSACCESS_EXT_BYTE_EN = 2, /* Support for Byte Enables. */
|
||||
|
||||
/*
|
||||
* Originally, all interrupt/wire updates over remote-port were posted.
|
||||
* This turned out to be a bad idea. To fix it without breaking backwards
|
||||
* compatibility, we add the WIRE Posted updates capability.
|
||||
*
|
||||
* If the peer supportes this, it will respect the RP_PKT_FLAGS_posted
|
||||
* flag. If the peer doesn't support this capability, senders need to
|
||||
* be aware that the peer will not respond to wire updates regardless
|
||||
* of the posted header-flag.
|
||||
*/
|
||||
CAP_WIRE_POSTED_UPDATES = 3,
|
||||
|
||||
CAP_ATS = 4, /* Address translation services */
|
||||
};
|
||||
|
||||
struct rp_pkt_hello {
|
||||
struct rp_pkt_hdr hdr;
|
||||
struct rp_version version;
|
||||
struct rp_capabilities caps;
|
||||
} PACKED;
|
||||
|
||||
enum {
|
||||
/* Remote port responses. */
|
||||
RP_RESP_OK = 0x0,
|
||||
RP_RESP_BUS_GENERIC_ERROR = 0x1,
|
||||
RP_RESP_ADDR_ERROR = 0x2,
|
||||
RP_RESP_MAX = 0xF,
|
||||
};
|
||||
|
||||
enum {
|
||||
RP_BUS_ATTR_EOP = (1 << 0),
|
||||
RP_BUS_ATTR_SECURE = (1 << 1),
|
||||
RP_BUS_ATTR_EXT_BASE = (1 << 2),
|
||||
RP_BUS_ATTR_PHYS_ADDR = (1 << 3),
|
||||
|
||||
/*
|
||||
* Bits [11:8] are allocated for storing transaction response codes.
|
||||
* These new response codes are backward compatible as existing
|
||||
* implementations will not set/read these bits.
|
||||
* For existing implementations, these bits will be zero which is RESP_OKAY.
|
||||
*/
|
||||
RP_BUS_RESP_SHIFT = 8,
|
||||
RP_BUS_RESP_MASK = (RP_RESP_MAX << RP_BUS_RESP_SHIFT),
|
||||
};
|
||||
|
||||
struct rp_pkt_busaccess {
|
||||
struct rp_pkt_hdr hdr;
|
||||
uint64_t timestamp;
|
||||
uint64_t attributes;
|
||||
uint64_t addr;
|
||||
|
||||
/* Length in bytes. */
|
||||
uint32_t len;
|
||||
|
||||
/* Width of each beat in bytes. Set to zero for unknown (let the remote
|
||||
side choose). */
|
||||
uint32_t width;
|
||||
|
||||
/* Width of streaming, must be a multiple of width.
|
||||
addr should repeat itself around this width. Set to same as len
|
||||
for incremental (normal) accesses. In bytes. */
|
||||
uint32_t stream_width;
|
||||
|
||||
/* Implementation specific source or master-id. */
|
||||
uint16_t master_id;
|
||||
} PACKED;
|
||||
|
||||
|
||||
/* This is the new extended busaccess packet layout. */
|
||||
struct rp_pkt_busaccess_ext_base {
|
||||
struct rp_pkt_hdr hdr;
|
||||
uint64_t timestamp;
|
||||
uint64_t attributes;
|
||||
uint64_t addr;
|
||||
|
||||
/* Length in bytes. */
|
||||
uint32_t len;
|
||||
|
||||
/* Width of each beat in bytes. Set to zero for unknown (let the remote
|
||||
side choose). */
|
||||
uint32_t width;
|
||||
|
||||
/* Width of streaming, must be a multiple of width.
|
||||
addr should repeat itself around this width. Set to same as len
|
||||
for incremental (normal) accesses. In bytes. */
|
||||
uint32_t stream_width;
|
||||
|
||||
/* Implementation specific source or master-id. */
|
||||
uint16_t master_id;
|
||||
/* ---- End of 4.0 base busaccess. ---- */
|
||||
|
||||
uint16_t master_id_31_16; /* MasterID bits [31:16]. */
|
||||
uint32_t master_id_63_32; /* MasterID bits [63:32]. */
|
||||
/* ---------------------------------------------------
|
||||
* Since hdr is 5 x 32bit, we are now 64bit aligned. */
|
||||
|
||||
uint32_t data_offset; /* Offset to data from start of pkt. */
|
||||
uint32_t next_offset; /* Offset to next extension. 0 if none. */
|
||||
|
||||
uint32_t byte_enable_offset;
|
||||
uint32_t byte_enable_len;
|
||||
|
||||
/* ---- End of CAP_BUSACCESS_EXT_BASE. ---- */
|
||||
|
||||
/* If new features are needed that may always occupy space
|
||||
* in the header, then add a new capability and extend the
|
||||
* this area with new fields.
|
||||
* Will help receivers find data_offset and next offset,
|
||||
* even those that don't know about extended fields.
|
||||
*/
|
||||
} PACKED;
|
||||
|
||||
struct rp_pkt_interrupt {
|
||||
struct rp_pkt_hdr hdr;
|
||||
uint64_t timestamp;
|
||||
uint64_t vector;
|
||||
uint32_t line;
|
||||
uint8_t val;
|
||||
} PACKED;
|
||||
|
||||
struct rp_pkt_sync {
|
||||
struct rp_pkt_hdr hdr;
|
||||
uint64_t timestamp;
|
||||
} PACKED;
|
||||
|
||||
enum {
|
||||
RP_ATS_ATTR_exec = 1 << 0,
|
||||
RP_ATS_ATTR_read = 1 << 1,
|
||||
RP_ATS_ATTR_write = 1 << 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
RP_ATS_RESULT_ok = 0,
|
||||
RP_ATS_RESULT_error = 1,
|
||||
};
|
||||
|
||||
struct rp_pkt_ats {
|
||||
struct rp_pkt_hdr hdr;
|
||||
uint64_t timestamp;
|
||||
uint64_t attributes;
|
||||
uint64_t addr;
|
||||
uint64_t len;
|
||||
uint32_t result;
|
||||
uint64_t reserved0;
|
||||
uint64_t reserved1;
|
||||
uint64_t reserved2;
|
||||
uint64_t reserved3;
|
||||
} PACKED;
|
||||
|
||||
struct rp_pkt {
|
||||
union {
|
||||
struct rp_pkt_hdr hdr;
|
||||
struct rp_pkt_hello hello;
|
||||
struct rp_pkt_busaccess busaccess;
|
||||
struct rp_pkt_busaccess_ext_base busaccess_ext_base;
|
||||
struct rp_pkt_interrupt interrupt;
|
||||
struct rp_pkt_sync sync;
|
||||
struct rp_pkt_ats ats;
|
||||
};
|
||||
};
|
||||
|
||||
struct rp_peer_state {
|
||||
void *opaque;
|
||||
|
||||
struct rp_pkt pkt;
|
||||
bool hdr_used;
|
||||
|
||||
struct rp_version version;
|
||||
|
||||
struct {
|
||||
bool busaccess_ext_base;
|
||||
bool busaccess_ext_byte_en;
|
||||
bool wire_posted_updates;
|
||||
bool ats;
|
||||
} caps;
|
||||
|
||||
/* Used to normalize our clk. */
|
||||
int64_t clk_base;
|
||||
|
||||
struct rp_cfg_state local_cfg;
|
||||
struct rp_cfg_state peer_cfg;
|
||||
};
|
||||
|
||||
const char *rp_cmd_to_string(enum rp_cmd cmd);
|
||||
int rp_decode_hdr(struct rp_pkt *pkt);
|
||||
int rp_decode_payload(struct rp_pkt *pkt);
|
||||
|
||||
void rp_encode_hdr(struct rp_pkt_hdr *hdr,
|
||||
uint32_t cmd, uint32_t id, uint32_t dev, uint32_t len,
|
||||
uint32_t flags);
|
||||
|
||||
/*
|
||||
* caps is a an array of supported capabilities by the implementor.
|
||||
* caps_out is the encoded (network byte order) version of the
|
||||
* same array. It should be sent to the peer after the hello packet.
|
||||
*/
|
||||
size_t rp_encode_hello_caps(uint32_t id, uint32_t dev, struct rp_pkt_hello *pkt,
|
||||
uint16_t version_major, uint16_t version_minor,
|
||||
uint32_t *caps, uint32_t *features_out,
|
||||
uint32_t features_len);
|
||||
|
||||
/* rp_encode_hello is deprecated in favor of hello_caps. */
|
||||
static inline size_t __attribute__ ((deprecated))
|
||||
rp_encode_hello(uint32_t id, uint32_t dev, struct rp_pkt_hello *pkt,
|
||||
uint16_t version_major, uint16_t version_minor) {
|
||||
return rp_encode_hello_caps(id, dev, pkt, version_major, version_minor,
|
||||
NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static inline void *__attribute__ ((deprecated))
|
||||
rp_busaccess_dataptr(struct rp_pkt_busaccess *pkt)
|
||||
{
|
||||
/* Right after the packet. */
|
||||
return pkt + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* rp_busaccess_rx_dataptr
|
||||
*
|
||||
* Predicts the dataptr for a packet to be transmitted.
|
||||
* This should only be used if you are trying to keep
|
||||
* the entire packet in a linear buffer.
|
||||
*/
|
||||
static inline unsigned char *
|
||||
rp_busaccess_tx_dataptr(struct rp_peer_state *peer,
|
||||
struct rp_pkt_busaccess_ext_base *pkt)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) pkt;
|
||||
|
||||
if (peer->caps.busaccess_ext_base) {
|
||||
/* We always put our data right after the header. */
|
||||
return p + sizeof *pkt;
|
||||
} else {
|
||||
/* Right after the old packet layout. */
|
||||
return p + sizeof(struct rp_pkt_busaccess);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rp_busaccess_rx_dataptr
|
||||
*
|
||||
* Extracts the dataptr from a received packet.
|
||||
*/
|
||||
static inline unsigned char *
|
||||
rp_busaccess_rx_dataptr(struct rp_peer_state *peer,
|
||||
struct rp_pkt_busaccess_ext_base *pkt)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) pkt;
|
||||
|
||||
if (pkt->attributes & RP_BUS_ATTR_EXT_BASE) {
|
||||
return p + pkt->data_offset;
|
||||
} else {
|
||||
/* Right after the old packet layout. */
|
||||
return p + sizeof(struct rp_pkt_busaccess);
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned char *
|
||||
rp_busaccess_byte_en_ptr(struct rp_peer_state *peer,
|
||||
struct rp_pkt_busaccess_ext_base *pkt)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) pkt;
|
||||
|
||||
if ((pkt->attributes & RP_BUS_ATTR_EXT_BASE)
|
||||
&& pkt->byte_enable_len) {
|
||||
assert(pkt->byte_enable_offset >= sizeof *pkt);
|
||||
assert(pkt->byte_enable_offset + pkt->byte_enable_len
|
||||
<= pkt->hdr.len + sizeof pkt->hdr);
|
||||
return p + pkt->byte_enable_offset;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t __attribute__ ((deprecated))
|
||||
rp_encode_read(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width);
|
||||
|
||||
size_t __attribute__ ((deprecated))
|
||||
rp_encode_read_resp(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width);
|
||||
|
||||
size_t __attribute__ ((deprecated))
|
||||
rp_encode_write(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width);
|
||||
|
||||
size_t __attribute__ ((deprecated))
|
||||
rp_encode_write_resp(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_busaccess *pkt,
|
||||
int64_t clk, uint16_t master_id,
|
||||
uint64_t addr, uint64_t attr, uint32_t size,
|
||||
uint32_t width, uint32_t stream_width);
|
||||
|
||||
struct rp_encode_busaccess_in {
|
||||
uint32_t cmd;
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
uint32_t dev;
|
||||
int64_t clk;
|
||||
uint64_t master_id;
|
||||
uint64_t addr;
|
||||
uint64_t attr;
|
||||
uint32_t size;
|
||||
uint32_t width;
|
||||
uint32_t stream_width;
|
||||
uint32_t byte_enable_len;
|
||||
};
|
||||
|
||||
/* Prepare encode_busaccess input parameters for a packet response. */
|
||||
static inline void
|
||||
rp_encode_busaccess_in_rsp_init(struct rp_encode_busaccess_in *in,
|
||||
struct rp_pkt *pkt) {
|
||||
memset(in, 0, sizeof *in);
|
||||
in->cmd = pkt->hdr.cmd;
|
||||
in->id = pkt->hdr.id;
|
||||
in->flags = pkt->hdr.flags | RP_PKT_FLAGS_response;
|
||||
in->dev = pkt->hdr.dev;
|
||||
/* FIXME: Propagate all master_id fields? */
|
||||
in->master_id = pkt->busaccess.master_id;
|
||||
in->addr = pkt->busaccess.addr;
|
||||
in->size = pkt->busaccess.len;
|
||||
in->width = pkt->busaccess.width;
|
||||
in->stream_width = pkt->busaccess.stream_width;
|
||||
in->byte_enable_len = 0;
|
||||
}
|
||||
size_t rp_encode_busaccess(struct rp_peer_state *peer,
|
||||
struct rp_pkt_busaccess_ext_base *pkt,
|
||||
struct rp_encode_busaccess_in *in);
|
||||
|
||||
size_t rp_encode_interrupt_f(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_interrupt *pkt,
|
||||
int64_t clk,
|
||||
uint32_t line, uint64_t vector, uint8_t val,
|
||||
uint32_t flags);
|
||||
|
||||
size_t rp_encode_interrupt(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_interrupt *pkt,
|
||||
int64_t clk,
|
||||
uint32_t line, uint64_t vector, uint8_t val);
|
||||
|
||||
size_t rp_encode_sync(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_sync *pkt,
|
||||
int64_t clk);
|
||||
|
||||
size_t rp_encode_sync_resp(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_sync *pkt,
|
||||
int64_t clk);
|
||||
|
||||
size_t rp_encode_ats_req(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_ats *pkt,
|
||||
int64_t clk, uint64_t attr, uint64_t addr,
|
||||
uint64_t size, uint64_t result, uint32_t flags);
|
||||
|
||||
size_t rp_encode_ats_inv(uint32_t id, uint32_t dev,
|
||||
struct rp_pkt_ats *pkt,
|
||||
int64_t clk, uint64_t attr, uint64_t addr,
|
||||
uint64_t size, uint64_t result, uint32_t flags);
|
||||
|
||||
void rp_process_caps(struct rp_peer_state *peer,
|
||||
void *caps, size_t caps_len);
|
||||
|
||||
/* Dynamically resizable remote port pkt. */
|
||||
|
||||
typedef struct RemotePortDynPkt {
|
||||
struct rp_pkt *pkt;
|
||||
size_t size;
|
||||
} RemotePortDynPkt;
|
||||
|
||||
/*
|
||||
* Make sure dpkt is allocated and has enough room.
|
||||
*/
|
||||
|
||||
void rp_dpkt_alloc(RemotePortDynPkt *dpkt, size_t size);
|
||||
|
||||
void rp_dpkt_swap(RemotePortDynPkt *a, RemotePortDynPkt *b);
|
||||
|
||||
/*
|
||||
* Check if the dpkt is valid. Used for debugging purposes.
|
||||
*/
|
||||
|
||||
bool rp_dpkt_is_valid(RemotePortDynPkt *dpkt);
|
||||
|
||||
/*
|
||||
* Invalidate the dpkt. Used for debugging purposes.
|
||||
*/
|
||||
|
||||
void rp_dpkt_invalidate(RemotePortDynPkt *dpkt);
|
||||
|
||||
void rp_dpkt_free(RemotePortDynPkt *dpkt);
|
||||
|
||||
static inline int rp_get_busaccess_response(struct rp_pkt *pkt)
|
||||
{
|
||||
return (pkt->busaccess_ext_base.attributes & RP_BUS_RESP_MASK) >>
|
||||
RP_BUS_RESP_SHIFT;
|
||||
}
|
||||
#endif
|
115
examples/zynq7000/SIM/tb_cosim.sv
Normal file
115
examples/zynq7000/SIM/tb_cosim.sv
Normal file
@ -0,0 +1,115 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_cosim;
|
||||
import "DPI-C" function int start_cosim(string path);
|
||||
import "DPI-C" function void end_cosim();
|
||||
import "DPI-C" function int wait_cosim(output int addr, output int t);
|
||||
import "DPI-C" function void finalize_cosim(int t);
|
||||
import "DPI-C" function void read_cosim(input int value);
|
||||
import "DPI-C" function int write_cosim();
|
||||
|
||||
// Cosimulation variables
|
||||
integer cosim_ret;
|
||||
reg unsigned [31:0] cosim_address;
|
||||
reg unsigned [31:0] cosim_data;
|
||||
integer timestamp;
|
||||
integer curtime;
|
||||
integer started;
|
||||
|
||||
reg ACLK;
|
||||
reg ARESETN;
|
||||
|
||||
wire [1:0] LED;
|
||||
|
||||
initial begin
|
||||
ACLK = 1'b0;
|
||||
ARESETN = 0'b0;
|
||||
end
|
||||
|
||||
always #5 ACLK = !ACLK;
|
||||
|
||||
initial begin
|
||||
$display("Starting testbench");
|
||||
// Start co-simulation
|
||||
if (start_cosim("unix:/tmp/qemu-rport-_cosim@0")>0) begin
|
||||
$display("ERROR: Could not start co-simulation. Stop simulation");
|
||||
$stop;
|
||||
end
|
||||
$display("Co-simulation started");
|
||||
|
||||
ARESETN = 1'b0;
|
||||
repeat(2)@(posedge ACLK);
|
||||
ARESETN = 1'b1;
|
||||
repeat(2)@(posedge ACLK);
|
||||
|
||||
// Main loop
|
||||
cosim_ret = 0;
|
||||
while (cosim_ret>=0) begin
|
||||
cosim_ret = wait_cosim(cosim_address, timestamp);
|
||||
|
||||
// Check for end of simulation
|
||||
if (cosim_address=='h7ffffffc) begin
|
||||
break;
|
||||
end
|
||||
|
||||
// Check for start of simulation
|
||||
if (cosim_address=='h7ffffff8) begin
|
||||
curtime = timestamp;
|
||||
cosim_ret = 0;
|
||||
started = 1;
|
||||
end
|
||||
|
||||
// Check for pause of simulation
|
||||
if (cosim_address=='h7ffffff4) begin
|
||||
started = 0;
|
||||
finalize_cosim(curtime);
|
||||
end
|
||||
|
||||
if (started==0) begin
|
||||
continue;
|
||||
end
|
||||
|
||||
while(curtime<timestamp) begin
|
||||
@(posedge ACLK);
|
||||
end
|
||||
|
||||
if (cosim_ret==1) begin
|
||||
// WRITE
|
||||
cosim_data = write_cosim();
|
||||
// ADDR = cosim_address;
|
||||
// WRDAT = cosim_data;
|
||||
// WR = 1'b1;
|
||||
@(posedge ACLK);
|
||||
// WR = 1'b0;
|
||||
// while (WRREADY==1'b0) begin
|
||||
// @(posedge ACLK);
|
||||
// end
|
||||
end
|
||||
|
||||
if (cosim_ret==2) begin
|
||||
// READ
|
||||
// ADDR = cosim_address;
|
||||
// RD = 1'b1;
|
||||
@(posedge ACLK);
|
||||
// RD = 1'b0;
|
||||
// while (RDREADY==1'b0) begin
|
||||
// @(posedge ACLK);
|
||||
// end
|
||||
@(negedge ACLK);
|
||||
cosim_data = 'hdeadbeef;
|
||||
read_cosim(cosim_data);
|
||||
end
|
||||
finalize_cosim(curtime);
|
||||
end
|
||||
|
||||
$display("Reached end of simulation. Stop Co-simulation");
|
||||
end_cosim();
|
||||
$stop;
|
||||
|
||||
end
|
||||
|
||||
heartbeat #(100000000, 10000000) i_heartbeat(
|
||||
ACLK, ARESETN, LED
|
||||
);
|
||||
|
||||
endmodule
|
2
examples/zynq7000/SW/.gitignore
vendored
Normal file
2
examples/zynq7000/SW/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
DISASS
|
68
examples/zynq7000/SW/Makefile
Normal file
68
examples/zynq7000/SW/Makefile
Normal file
@ -0,0 +1,68 @@
|
||||
.SILENT:
|
||||
|
||||
TARGET := app.elf
|
||||
|
||||
BUILDROOT ?= $(shell pwd)
|
||||
BUILDDIR := build
|
||||
|
||||
SRCDIRS := $(BUILDROOT)/src
|
||||
SRCFILESC := $(shell find $(SRCDIRS) -type f -name "*.c")
|
||||
OBJFILESC := $(SRCFILESC:%.c=$(BUILDDIR)/%.c.o) $(BUILDDIR)/src/ps7_init.o
|
||||
DEPFILESC := $(SRCFILESC:%.c=$(BUILDDIR)/%.c.d)
|
||||
SRCFILESA := $(shell find $(SRCDIRS) -type f -name "*.S")
|
||||
OBJFILESA := $(SRCFILESA:%.S=$(BUILDDIR)/%.S.o)
|
||||
DEPFILESA := $(SRCFILESA:%.S=$(BUILDDIR)/%.S.d)
|
||||
SRCFILES := $(SRCFILESC) $(SRCFILESA)
|
||||
OBJFILES := $(OBJFILESA) $(OBJFILESC)
|
||||
DEPFILES := $(DEPFILESC) $(DEPFILESA)
|
||||
|
||||
FILESTOCLEAN := $(OBJFILES) $(DEPFILES) $(BUILDDIR)/$(TARGET)
|
||||
|
||||
CROSS_COMPILE ?= arm-none-eabi-
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
AS := $(CROSS_COMPILE)as
|
||||
LD := $(CROSS_COMPILE)gcc
|
||||
|
||||
CC_WARNING := -Wall -Wextra
|
||||
CC_LIBS := -lgcc
|
||||
CC_FLAGS := -nostdlib -fno-builtin -g -mcpu=cortex-a9
|
||||
CC_INCLUDES := -I $(BUILDROOT)/src -I $(BUILDROOT)/../OUT/ip/zynqps
|
||||
LD_FLAGS := -Wl,-T$(BUILDROOT)/linker.ld
|
||||
|
||||
.PHONY: $(TARGET) all clean
|
||||
all: $(TARGET)
|
||||
|
||||
# PHONY RULES
|
||||
# -----------
|
||||
|
||||
$(TARGET): $(BUILDDIR)/$(TARGET)
|
||||
|
||||
clean:
|
||||
echo CLEAN FILES FOR $(TARGET)
|
||||
-rm -r $(FILESTOCLEAN)
|
||||
|
||||
# SPECIFIC BUILD RULES
|
||||
# --------------------
|
||||
|
||||
$(BUILDDIR)/$(TARGET): $(OBJFILES)
|
||||
echo 'LD ' $@
|
||||
$(LD) $(CC_FLAGS) $(LD_FLAGS) -o $(BUILDDIR)/$(TARGET) $(OBJFILES) $(CC_LIBS)
|
||||
$(XILINX_BASE)/bin/$(CROSS_COMPILE)objdump -D $(BUILDDIR)/$(TARGET) > DISASS
|
||||
|
||||
$(BUILDDIR)/src/ps7_init.o : $(BUILDROOT)/../OUT/ip/zynqps/ps7_init.c $(BUILDROOT)/../OUT/ip/zynqps/ps7_init.h
|
||||
echo 'CC ' $@
|
||||
-mkdir -p $(shell dirname $@)
|
||||
$(CC) $(CC_FLAGS) $(CC_WARNING) $(CC_INCLUDES) -MD -o $(BUILDDIR)/src/ps7_init.o -c $(BUILDROOT)/../OUT/ip/zynqps/ps7_init.c
|
||||
|
||||
$(OBJFILES): $(BUILDDIR)/%.c.o: %.c
|
||||
echo 'CC ' $@
|
||||
-mkdir -p $(shell dirname $@)
|
||||
$(CC) $(CC_FLAGS) $(CC_WARNING) $(CC_INCLUDES) -MD -o $@ -c $<
|
||||
|
||||
$(OBJFILESA): $(BUILDDIR)/%.S.o: %.S
|
||||
echo 'AS ' $@
|
||||
-mkdir -p $(shell dirname $@)
|
||||
$(CC) $(CC_FLAGS) $(CC_WARNING) $(CC_INCLUDES) -MD -o $@ -c $<
|
||||
|
||||
# Add DEPFILE dependencies
|
||||
-include $(DEPFILES)
|
13
examples/zynq7000/SW/devicetree/Makefile
Normal file
13
examples/zynq7000/SW/devicetree/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
.SILENT:
|
||||
|
||||
TARGET := system.dtb
|
||||
|
||||
BUILDROOT ?= $(shell pwd)
|
||||
BUILDDIR := build
|
||||
|
||||
.PHONY: $(TARGET) all clean
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET):
|
||||
gcc -I $(BUILDROOT) -I $(BUILDROOT)/include -E -nostdinc -undef -D__DTS__ -x assembler-with-cpp -o system.dts $(BUILDROOT)/system-top.dts
|
||||
dtc -I dts -O dtb -o system.dtb system.dts
|
@ -0,0 +1,123 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2019 Xilinx Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLK_VERSAL_H
|
||||
#define _DT_BINDINGS_CLK_VERSAL_H
|
||||
|
||||
#define PMC_PLL 1
|
||||
#define APU_PLL 2
|
||||
#define RPU_PLL 3
|
||||
#define CPM_PLL 4
|
||||
#define NOC_PLL 5
|
||||
#define PLL_MAX 6
|
||||
#define PMC_PRESRC 7
|
||||
#define PMC_POSTCLK 8
|
||||
#define PMC_PLL_OUT 9
|
||||
#define PPLL 10
|
||||
#define NOC_PRESRC 11
|
||||
#define NOC_POSTCLK 12
|
||||
#define NOC_PLL_OUT 13
|
||||
#define NPLL 14
|
||||
#define APU_PRESRC 15
|
||||
#define APU_POSTCLK 16
|
||||
#define APU_PLL_OUT 17
|
||||
#define APLL 18
|
||||
#define RPU_PRESRC 19
|
||||
#define RPU_POSTCLK 20
|
||||
#define RPU_PLL_OUT 21
|
||||
#define RPLL 22
|
||||
#define CPM_PRESRC 23
|
||||
#define CPM_POSTCLK 24
|
||||
#define CPM_PLL_OUT 25
|
||||
#define CPLL 26
|
||||
#define PPLL_TO_XPD 27
|
||||
#define NPLL_TO_XPD 28
|
||||
#define APLL_TO_XPD 29
|
||||
#define RPLL_TO_XPD 30
|
||||
#define EFUSE_REF 31
|
||||
#define SYSMON_REF 32
|
||||
#define IRO_SUSPEND_REF 33
|
||||
#define USB_SUSPEND 34
|
||||
#define SWITCH_TIMEOUT 35
|
||||
#define RCLK_PMC 36
|
||||
#define RCLK_LPD 37
|
||||
#define WDT 38
|
||||
#define TTC0 39
|
||||
#define TTC1 40
|
||||
#define TTC2 41
|
||||
#define TTC3 42
|
||||
#define GEM_TSU 43
|
||||
#define GEM_TSU_LB 44
|
||||
#define MUXED_IRO_DIV2 45
|
||||
#define MUXED_IRO_DIV4 46
|
||||
#define PSM_REF 47
|
||||
#define GEM0_RX 48
|
||||
#define GEM0_TX 49
|
||||
#define GEM1_RX 50
|
||||
#define GEM1_TX 51
|
||||
#define CPM_CORE_REF 52
|
||||
#define CPM_LSBUS_REF 53
|
||||
#define CPM_DBG_REF 54
|
||||
#define CPM_AUX0_REF 55
|
||||
#define CPM_AUX1_REF 56
|
||||
#define QSPI_REF 57
|
||||
#define OSPI_REF 58
|
||||
#define SDIO0_REF 59
|
||||
#define SDIO1_REF 60
|
||||
#define PMC_LSBUS_REF 61
|
||||
#define I2C_REF 62
|
||||
#define TEST_PATTERN_REF 63
|
||||
#define DFT_OSC_REF 64
|
||||
#define PMC_PL0_REF 65
|
||||
#define PMC_PL1_REF 66
|
||||
#define PMC_PL2_REF 67
|
||||
#define PMC_PL3_REF 68
|
||||
#define CFU_REF 69
|
||||
#define SPARE_REF 70
|
||||
#define NPI_REF 71
|
||||
#define HSM0_REF 72
|
||||
#define HSM1_REF 73
|
||||
#define SD_DLL_REF 74
|
||||
#define FPD_TOP_SWITCH 75
|
||||
#define FPD_LSBUS 76
|
||||
#define ACPU 77
|
||||
#define DBG_TRACE 78
|
||||
#define DBG_FPD 79
|
||||
#define LPD_TOP_SWITCH 80
|
||||
#define ADMA 81
|
||||
#define LPD_LSBUS 82
|
||||
#define CPU_R5 83
|
||||
#define CPU_R5_CORE 84
|
||||
#define CPU_R5_OCM 85
|
||||
#define CPU_R5_OCM2 86
|
||||
#define IOU_SWITCH 87
|
||||
#define GEM0_REF 88
|
||||
#define GEM1_REF 89
|
||||
#define GEM_TSU_REF 90
|
||||
#define USB0_BUS_REF 91
|
||||
#define UART0_REF 92
|
||||
#define UART1_REF 93
|
||||
#define SPI0_REF 94
|
||||
#define SPI1_REF 95
|
||||
#define CAN0_REF 96
|
||||
#define CAN1_REF 97
|
||||
#define I2C0_REF 98
|
||||
#define I2C1_REF 99
|
||||
#define DBG_LPD 100
|
||||
#define TIMESTAMP_REF 101
|
||||
#define DBG_TSTMP 102
|
||||
#define CPM_TOPSW_REF 103
|
||||
#define USB3_DUAL_REF 104
|
||||
#define OUTCLK_MAX 105
|
||||
#define REF_CLK 106
|
||||
#define PL_ALT_REF_CLK 107
|
||||
#define MUXED_IRO 108
|
||||
#define PL_EXT 109
|
||||
#define PL_LB 110
|
||||
#define MIO_50_OR_51 111
|
||||
#define MIO_24_OR_25 112
|
||||
|
||||
#endif
|
@ -0,0 +1,42 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2019 Xilinx, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_VERSAL_POWER_H
|
||||
#define _DT_BINDINGS_VERSAL_POWER_H
|
||||
|
||||
#define PM_DEV_USB_0 (0x18224018U)
|
||||
#define PM_DEV_GEM_0 (0x18224019U)
|
||||
#define PM_DEV_GEM_1 (0x1822401aU)
|
||||
#define PM_DEV_SPI_0 (0x1822401bU)
|
||||
#define PM_DEV_SPI_1 (0x1822401cU)
|
||||
#define PM_DEV_I2C_0 (0x1822401dU)
|
||||
#define PM_DEV_I2C_1 (0x1822401eU)
|
||||
#define PM_DEV_CAN_FD_0 (0x1822401fU)
|
||||
#define PM_DEV_CAN_FD_1 (0x18224020U)
|
||||
#define PM_DEV_UART_0 (0x18224021U)
|
||||
#define PM_DEV_UART_1 (0x18224022U)
|
||||
#define PM_DEV_GPIO (0x18224023U)
|
||||
#define PM_DEV_TTC_0 (0x18224024U)
|
||||
#define PM_DEV_TTC_1 (0x18224025U)
|
||||
#define PM_DEV_TTC_2 (0x18224026U)
|
||||
#define PM_DEV_TTC_3 (0x18224027U)
|
||||
#define PM_DEV_SWDT_FPD (0x18224029U)
|
||||
#define PM_DEV_OSPI (0x1822402aU)
|
||||
#define PM_DEV_QSPI (0x1822402bU)
|
||||
#define PM_DEV_GPIO_PMC (0x1822402cU)
|
||||
#define PM_DEV_SDIO_0 (0x1822402eU)
|
||||
#define PM_DEV_SDIO_1 (0x1822402fU)
|
||||
#define PM_DEV_RTC (0x18224034U)
|
||||
#define PM_DEV_ADMA_0 (0x18224035U)
|
||||
#define PM_DEV_ADMA_1 (0x18224036U)
|
||||
#define PM_DEV_ADMA_2 (0x18224037U)
|
||||
#define PM_DEV_ADMA_3 (0x18224038U)
|
||||
#define PM_DEV_ADMA_4 (0x18224039U)
|
||||
#define PM_DEV_ADMA_5 (0x1822403aU)
|
||||
#define PM_DEV_ADMA_6 (0x1822403bU)
|
||||
#define PM_DEV_ADMA_7 (0x1822403cU)
|
||||
#define PM_DEV_AI (0x18224072U)
|
||||
|
||||
#endif
|
@ -0,0 +1,130 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 Xilinx, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_ZYNQMP_RESETS_H
|
||||
#define _DT_BINDINGS_ZYNQMP_RESETS_H
|
||||
|
||||
#define ZYNQMP_RESET_PCIE_CFG 0
|
||||
#define ZYNQMP_RESET_PCIE_BRIDGE 1
|
||||
#define ZYNQMP_RESET_PCIE_CTRL 2
|
||||
#define ZYNQMP_RESET_DP 3
|
||||
#define ZYNQMP_RESET_SWDT_CRF 4
|
||||
#define ZYNQMP_RESET_AFI_FM5 5
|
||||
#define ZYNQMP_RESET_AFI_FM4 6
|
||||
#define ZYNQMP_RESET_AFI_FM3 7
|
||||
#define ZYNQMP_RESET_AFI_FM2 8
|
||||
#define ZYNQMP_RESET_AFI_FM1 9
|
||||
#define ZYNQMP_RESET_AFI_FM0 10
|
||||
#define ZYNQMP_RESET_GDMA 11
|
||||
#define ZYNQMP_RESET_GPU_PP1 12
|
||||
#define ZYNQMP_RESET_GPU_PP0 13
|
||||
#define ZYNQMP_RESET_GPU 14
|
||||
#define ZYNQMP_RESET_GT 15
|
||||
#define ZYNQMP_RESET_SATA 16
|
||||
#define ZYNQMP_RESET_ACPU3_PWRON 17
|
||||
#define ZYNQMP_RESET_ACPU2_PWRON 18
|
||||
#define ZYNQMP_RESET_ACPU1_PWRON 19
|
||||
#define ZYNQMP_RESET_ACPU0_PWRON 20
|
||||
#define ZYNQMP_RESET_APU_L2 21
|
||||
#define ZYNQMP_RESET_ACPU3 22
|
||||
#define ZYNQMP_RESET_ACPU2 23
|
||||
#define ZYNQMP_RESET_ACPU1 24
|
||||
#define ZYNQMP_RESET_ACPU0 25
|
||||
#define ZYNQMP_RESET_DDR 26
|
||||
#define ZYNQMP_RESET_APM_FPD 27
|
||||
#define ZYNQMP_RESET_SOFT 28
|
||||
#define ZYNQMP_RESET_GEM0 29
|
||||
#define ZYNQMP_RESET_GEM1 30
|
||||
#define ZYNQMP_RESET_GEM2 31
|
||||
#define ZYNQMP_RESET_GEM3 32
|
||||
#define ZYNQMP_RESET_QSPI 33
|
||||
#define ZYNQMP_RESET_UART0 34
|
||||
#define ZYNQMP_RESET_UART1 35
|
||||
#define ZYNQMP_RESET_SPI0 36
|
||||
#define ZYNQMP_RESET_SPI1 37
|
||||
#define ZYNQMP_RESET_SDIO0 38
|
||||
#define ZYNQMP_RESET_SDIO1 39
|
||||
#define ZYNQMP_RESET_CAN0 40
|
||||
#define ZYNQMP_RESET_CAN1 41
|
||||
#define ZYNQMP_RESET_I2C0 42
|
||||
#define ZYNQMP_RESET_I2C1 43
|
||||
#define ZYNQMP_RESET_TTC0 44
|
||||
#define ZYNQMP_RESET_TTC1 45
|
||||
#define ZYNQMP_RESET_TTC2 46
|
||||
#define ZYNQMP_RESET_TTC3 47
|
||||
#define ZYNQMP_RESET_SWDT_CRL 48
|
||||
#define ZYNQMP_RESET_NAND 49
|
||||
#define ZYNQMP_RESET_ADMA 50
|
||||
#define ZYNQMP_RESET_GPIO 51
|
||||
#define ZYNQMP_RESET_IOU_CC 52
|
||||
#define ZYNQMP_RESET_TIMESTAMP 53
|
||||
#define ZYNQMP_RESET_RPU_R50 54
|
||||
#define ZYNQMP_RESET_RPU_R51 55
|
||||
#define ZYNQMP_RESET_RPU_AMBA 56
|
||||
#define ZYNQMP_RESET_OCM 57
|
||||
#define ZYNQMP_RESET_RPU_PGE 58
|
||||
#define ZYNQMP_RESET_USB0_CORERESET 59
|
||||
#define ZYNQMP_RESET_USB1_CORERESET 60
|
||||
#define ZYNQMP_RESET_USB0_HIBERRESET 61
|
||||
#define ZYNQMP_RESET_USB1_HIBERRESET 62
|
||||
#define ZYNQMP_RESET_USB0_APB 63
|
||||
#define ZYNQMP_RESET_USB1_APB 64
|
||||
#define ZYNQMP_RESET_IPI 65
|
||||
#define ZYNQMP_RESET_APM_LPD 66
|
||||
#define ZYNQMP_RESET_RTC 67
|
||||
#define ZYNQMP_RESET_SYSMON 68
|
||||
#define ZYNQMP_RESET_AFI_FM6 69
|
||||
#define ZYNQMP_RESET_LPD_SWDT 70
|
||||
#define ZYNQMP_RESET_FPD 71
|
||||
#define ZYNQMP_RESET_RPU_DBG1 72
|
||||
#define ZYNQMP_RESET_RPU_DBG0 73
|
||||
#define ZYNQMP_RESET_DBG_LPD 74
|
||||
#define ZYNQMP_RESET_DBG_FPD 75
|
||||
#define ZYNQMP_RESET_APLL 76
|
||||
#define ZYNQMP_RESET_DPLL 77
|
||||
#define ZYNQMP_RESET_VPLL 78
|
||||
#define ZYNQMP_RESET_IOPLL 79
|
||||
#define ZYNQMP_RESET_RPLL 80
|
||||
#define ZYNQMP_RESET_GPO3_PL_0 81
|
||||
#define ZYNQMP_RESET_GPO3_PL_1 82
|
||||
#define ZYNQMP_RESET_GPO3_PL_2 83
|
||||
#define ZYNQMP_RESET_GPO3_PL_3 84
|
||||
#define ZYNQMP_RESET_GPO3_PL_4 85
|
||||
#define ZYNQMP_RESET_GPO3_PL_5 86
|
||||
#define ZYNQMP_RESET_GPO3_PL_6 87
|
||||
#define ZYNQMP_RESET_GPO3_PL_7 88
|
||||
#define ZYNQMP_RESET_GPO3_PL_8 89
|
||||
#define ZYNQMP_RESET_GPO3_PL_9 90
|
||||
#define ZYNQMP_RESET_GPO3_PL_10 91
|
||||
#define ZYNQMP_RESET_GPO3_PL_11 92
|
||||
#define ZYNQMP_RESET_GPO3_PL_12 93
|
||||
#define ZYNQMP_RESET_GPO3_PL_13 94
|
||||
#define ZYNQMP_RESET_GPO3_PL_14 95
|
||||
#define ZYNQMP_RESET_GPO3_PL_15 96
|
||||
#define ZYNQMP_RESET_GPO3_PL_16 97
|
||||
#define ZYNQMP_RESET_GPO3_PL_17 98
|
||||
#define ZYNQMP_RESET_GPO3_PL_18 99
|
||||
#define ZYNQMP_RESET_GPO3_PL_19 100
|
||||
#define ZYNQMP_RESET_GPO3_PL_20 101
|
||||
#define ZYNQMP_RESET_GPO3_PL_21 102
|
||||
#define ZYNQMP_RESET_GPO3_PL_22 103
|
||||
#define ZYNQMP_RESET_GPO3_PL_23 104
|
||||
#define ZYNQMP_RESET_GPO3_PL_24 105
|
||||
#define ZYNQMP_RESET_GPO3_PL_25 106
|
||||
#define ZYNQMP_RESET_GPO3_PL_26 107
|
||||
#define ZYNQMP_RESET_GPO3_PL_27 108
|
||||
#define ZYNQMP_RESET_GPO3_PL_28 109
|
||||
#define ZYNQMP_RESET_GPO3_PL_29 110
|
||||
#define ZYNQMP_RESET_GPO3_PL_30 111
|
||||
#define ZYNQMP_RESET_GPO3_PL_31 112
|
||||
#define ZYNQMP_RESET_RPU_LS 113
|
||||
#define ZYNQMP_RESET_PS_ONLY 114
|
||||
#define ZYNQMP_RESET_PL 115
|
||||
#define ZYNQMP_RESET_PS_PL0 116
|
||||
#define ZYNQMP_RESET_PS_PL1 117
|
||||
#define ZYNQMP_RESET_PS_PL2 118
|
||||
#define ZYNQMP_RESET_PS_PL3 119
|
||||
|
||||
#endif
|
28
examples/zynq7000/SW/devicetree/pcw.dtsi
Normal file
28
examples/zynq7000/SW/devicetree/pcw.dtsi
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* CAUTION: This file is automatically generated by Xilinx.
|
||||
* Version: XSCT 2020.2
|
||||
* Today is: Wed Oct 13 14:26:41 2021
|
||||
*/
|
||||
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
cpu@0 {
|
||||
operating-points = <666666 1000000 333333 1000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
&intc {
|
||||
num_cpus = <2>;
|
||||
num_interrupts = <96>;
|
||||
};
|
||||
&uart1 {
|
||||
cts-override ;
|
||||
device_type = "serial";
|
||||
port-number = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
&clkc {
|
||||
fclk-enable = <0x1>;
|
||||
ps-clk-frequency = <33333333>;
|
||||
};
|
35
examples/zynq7000/SW/devicetree/pl.dtsi
Normal file
35
examples/zynq7000/SW/devicetree/pl.dtsi
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* CAUTION: This file is automatically generated by Xilinx.
|
||||
* Version: XSCT 2020.2
|
||||
* Today is: Wed Oct 13 14:26:41 2021
|
||||
*/
|
||||
|
||||
|
||||
/ {
|
||||
amba_pl: amba_pl {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
ranges ;
|
||||
axi_gpio_0: gpio@41200000 {
|
||||
#gpio-cells = <3>;
|
||||
clock-names = "s_axi_aclk";
|
||||
clocks = <&clkc 15>;
|
||||
compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
|
||||
gpio-controller ;
|
||||
reg = <0x41200000 0x10000>;
|
||||
xlnx,all-inputs = <0x0>;
|
||||
xlnx,all-inputs-2 = <0x0>;
|
||||
xlnx,all-outputs = <0x0>;
|
||||
xlnx,all-outputs-2 = <0x0>;
|
||||
xlnx,dout-default = <0x00000000>;
|
||||
xlnx,dout-default-2 = <0x00000000>;
|
||||
xlnx,gpio-width = <0x20>;
|
||||
xlnx,gpio2-width = <0x20>;
|
||||
xlnx,interrupt-present = <0x0>;
|
||||
xlnx,is-dual = <0x0>;
|
||||
xlnx,tri-default = <0xFFFFFFFF>;
|
||||
xlnx,tri-default-2 = <0xFFFFFFFF>;
|
||||
};
|
||||
};
|
||||
};
|
13
examples/zynq7000/SW/devicetree/skeleton.dtsi
Normal file
13
examples/zynq7000/SW/devicetree/skeleton.dtsi
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Skeleton device tree; the bare minimum needed to boot; just include and
|
||||
* add a compatible value. The bootloader will typically populate the memory
|
||||
* node.
|
||||
*/
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
chosen { };
|
||||
aliases { };
|
||||
memory { device_type = "memory"; reg = <0 0>; };
|
||||
};
|
25
examples/zynq7000/SW/devicetree/system-top.dts
Normal file
25
examples/zynq7000/SW/devicetree/system-top.dts
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* CAUTION: This file is automatically generated by Xilinx.
|
||||
* Version: XSCT 2020.2
|
||||
* Today is: Wed Oct 13 14:26:41 2021
|
||||
*/
|
||||
|
||||
|
||||
/dts-v1/;
|
||||
#include "zynq-7000.dtsi"
|
||||
#include "zynq-pl-remoteport.dtsi"
|
||||
//#include "pl.dtsi"
|
||||
#include "pcw.dtsi"
|
||||
/ {
|
||||
chosen {
|
||||
bootargs = "earlycon";
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
aliases {
|
||||
serial0 = &uart1;
|
||||
};
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x20000000>;
|
||||
};
|
||||
};
|
566
examples/zynq7000/SW/devicetree/zynq-7000.dtsi
Normal file
566
examples/zynq7000/SW/devicetree/zynq-7000.dtsi
Normal file
@ -0,0 +1,566 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2011 - 2015 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "xlnx,zynq-7000";
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu0: cpu@0 {
|
||||
compatible = "arm,cortex-a9";
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
clocks = <&clkc 3>;
|
||||
clock-latency = <1000>;
|
||||
cpu0-supply = <®ulator_vccpint>;
|
||||
operating-points = <
|
||||
/* kHz uV */
|
||||
666667 1000000
|
||||
333334 1000000
|
||||
>;
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
compatible = "arm,cortex-a9";
|
||||
device_type = "cpu";
|
||||
reg = <1>;
|
||||
clocks = <&clkc 3>;
|
||||
};
|
||||
};
|
||||
|
||||
fpga_full: fpga-full {
|
||||
compatible = "fpga-region";
|
||||
fpga-mgr = <&devcfg>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
};
|
||||
|
||||
pmu@f8891000 {
|
||||
compatible = "arm,cortex-a9-pmu";
|
||||
interrupts = <0 5 4>, <0 6 4>;
|
||||
interrupt-parent = <&intc>;
|
||||
reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
|
||||
};
|
||||
|
||||
regulator_vccpint: fixedregulator {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VCCPINT";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
replicator {
|
||||
compatible = "arm,coresight-static-replicator";
|
||||
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
|
||||
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
|
||||
|
||||
out-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* replicator output ports */
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
replicator_out_port0: endpoint {
|
||||
remote-endpoint = <&tpiu_in_port>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
replicator_out_port1: endpoint {
|
||||
remote-endpoint = <&etb_in_port>;
|
||||
};
|
||||
};
|
||||
};
|
||||
in-ports {
|
||||
/* replicator input port */
|
||||
port {
|
||||
replicator_in_port0: endpoint {
|
||||
remote-endpoint = <&funnel_out_port>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
amba: amba {
|
||||
u-boot,dm-pre-reloc;
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&intc>;
|
||||
ranges;
|
||||
|
||||
adc: adc@f8007100 {
|
||||
compatible = "xlnx,zynq-xadc-1.00.a";
|
||||
reg = <0xf8007100 0x20>;
|
||||
interrupts = <0 7 4>;
|
||||
interrupt-parent = <&intc>;
|
||||
clocks = <&clkc 12>;
|
||||
};
|
||||
|
||||
can0: can@e0008000 {
|
||||
compatible = "xlnx,zynq-can-1.0";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 19>, <&clkc 36>;
|
||||
clock-names = "can_clk", "pclk";
|
||||
reg = <0xe0008000 0x1000>;
|
||||
interrupts = <0 28 4>;
|
||||
interrupt-parent = <&intc>;
|
||||
tx-fifo-depth = <0x40>;
|
||||
rx-fifo-depth = <0x40>;
|
||||
};
|
||||
|
||||
can1: can@e0009000 {
|
||||
compatible = "xlnx,zynq-can-1.0";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 20>, <&clkc 37>;
|
||||
clock-names = "can_clk", "pclk";
|
||||
reg = <0xe0009000 0x1000>;
|
||||
interrupts = <0 51 4>;
|
||||
interrupt-parent = <&intc>;
|
||||
tx-fifo-depth = <0x40>;
|
||||
rx-fifo-depth = <0x40>;
|
||||
};
|
||||
|
||||
gpio0: gpio@e000a000 {
|
||||
compatible = "xlnx,zynq-gpio-1.0";
|
||||
#gpio-cells = <2>;
|
||||
clocks = <&clkc 42>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 20 4>;
|
||||
reg = <0xe000a000 0x1000>;
|
||||
};
|
||||
|
||||
i2c0: i2c@e0004000 {
|
||||
compatible = "cdns,i2c-r1p10";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 38>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 25 4>;
|
||||
reg = <0xe0004000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c1: i2c@e0005000 {
|
||||
compatible = "cdns,i2c-r1p10";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 39>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 48 4>;
|
||||
reg = <0xe0005000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
intc: interrupt-controller@f8f01000 {
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
#interrupt-cells = <3>;
|
||||
interrupt-controller;
|
||||
reg = <0xF8F01000 0x1000>,
|
||||
<0xF8F00100 0x100>;
|
||||
};
|
||||
|
||||
L2: cache-controller@f8f02000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0xF8F02000 0x1000>;
|
||||
interrupts = <0 2 4>;
|
||||
arm,data-latency = <3 2 2>;
|
||||
arm,tag-latency = <2 2 2>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
};
|
||||
|
||||
mc: memory-controller@f8006000 {
|
||||
compatible = "xlnx,zynq-ddrc-a05";
|
||||
reg = <0xf8006000 0x1000>;
|
||||
};
|
||||
|
||||
ocmc: ocmc@f800c000 {
|
||||
compatible = "xlnx,zynq-ocmc-1.0";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 3 4>;
|
||||
reg = <0xf800c000 0x1000>;
|
||||
};
|
||||
|
||||
uart0: serial@e0000000 {
|
||||
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 23>, <&clkc 40>;
|
||||
clock-names = "uart_clk", "pclk";
|
||||
reg = <0xE0000000 0x1000>;
|
||||
interrupts = <0 27 4>;
|
||||
};
|
||||
|
||||
uart1: serial@e0001000 {
|
||||
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 24>, <&clkc 41>;
|
||||
clock-names = "uart_clk", "pclk";
|
||||
reg = <0xE0001000 0x1000>;
|
||||
interrupts = <0 50 4>;
|
||||
};
|
||||
|
||||
spi0: spi@e0006000 {
|
||||
compatible = "xlnx,zynq-spi-r1p6";
|
||||
reg = <0xe0006000 0x1000>;
|
||||
status = "disabled";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 26 4>;
|
||||
clocks = <&clkc 25>, <&clkc 34>;
|
||||
clock-names = "ref_clk", "pclk";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi1: spi@e0007000 {
|
||||
compatible = "xlnx,zynq-spi-r1p6";
|
||||
reg = <0xe0007000 0x1000>;
|
||||
status = "disabled";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 49 4>;
|
||||
clocks = <&clkc 26>, <&clkc 35>;
|
||||
clock-names = "ref_clk", "pclk";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
qspi: spi@e000d000 {
|
||||
clock-names = "ref_clk", "pclk";
|
||||
clocks = <&clkc 10>, <&clkc 43>;
|
||||
compatible = "xlnx,zynq-qspi-1.0";
|
||||
status = "disabled";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 19 4>;
|
||||
reg = <0xe000d000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
smcc: memory-controller@e000e000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
status = "disabled";
|
||||
clock-names = "memclk", "apb_pclk";
|
||||
clocks = <&clkc 11>, <&clkc 44>;
|
||||
compatible = "arm,pl353-smc-r2p1", "arm,primecell";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 18 4>;
|
||||
ranges ;
|
||||
reg = <0xe000e000 0x1000>;
|
||||
nand0: flash@e1000000 {
|
||||
status = "disabled";
|
||||
compatible = "arm,pl353-nand-r2p1";
|
||||
reg = <0xe1000000 0x1000000>;
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
};
|
||||
nor0: flash@e2000000 {
|
||||
status = "disabled";
|
||||
compatible = "cfi-flash";
|
||||
reg = <0xe2000000 0x2000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
gem0: ethernet@e000b000 {
|
||||
compatible = "cdns,zynq-gem", "cdns,gem";
|
||||
reg = <0xe000b000 0x1000>;
|
||||
status = "disabled";
|
||||
interrupts = <0 22 4>;
|
||||
clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
|
||||
clock-names = "pclk", "hclk", "tx_clk";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
gem1: ethernet@e000c000 {
|
||||
compatible = "cdns,zynq-gem", "cdns,gem";
|
||||
reg = <0xe000c000 0x1000>;
|
||||
status = "disabled";
|
||||
interrupts = <0 45 4>;
|
||||
clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>;
|
||||
clock-names = "pclk", "hclk", "tx_clk";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sdhci0: mmc@e0100000 {
|
||||
compatible = "arasan,sdhci-8.9a";
|
||||
status = "disabled";
|
||||
clock-names = "clk_xin", "clk_ahb";
|
||||
clocks = <&clkc 21>, <&clkc 32>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 24 4>;
|
||||
reg = <0xe0100000 0x1000>;
|
||||
};
|
||||
|
||||
sdhci1: mmc@e0101000 {
|
||||
compatible = "arasan,sdhci-8.9a";
|
||||
status = "disabled";
|
||||
clock-names = "clk_xin", "clk_ahb";
|
||||
clocks = <&clkc 22>, <&clkc 33>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 47 4>;
|
||||
reg = <0xe0101000 0x1000>;
|
||||
};
|
||||
|
||||
slcr: slcr@f8000000 {
|
||||
u-boot,dm-pre-reloc;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd";
|
||||
reg = <0xF8000000 0x1000>;
|
||||
ranges;
|
||||
clkc: clkc@100 {
|
||||
u-boot,dm-pre-reloc;
|
||||
#clock-cells = <1>;
|
||||
compatible = "xlnx,ps7-clkc";
|
||||
fclk-enable = <0xf>;
|
||||
clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
|
||||
"cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
|
||||
"dci", "lqspi", "smc", "pcap", "gem0", "gem1",
|
||||
"fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1",
|
||||
"sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1",
|
||||
"dma", "usb0_aper", "usb1_aper", "gem0_aper",
|
||||
"gem1_aper", "sdio0_aper", "sdio1_aper",
|
||||
"spi0_aper", "spi1_aper", "can0_aper", "can1_aper",
|
||||
"i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper",
|
||||
"gpio_aper", "lqspi_aper", "smc_aper", "swdt",
|
||||
"dbg_trc", "dbg_apb";
|
||||
reg = <0x100 0x100>;
|
||||
};
|
||||
|
||||
rstc: rstc@200 {
|
||||
compatible = "xlnx,zynq-reset";
|
||||
reg = <0x200 0x48>;
|
||||
#reset-cells = <1>;
|
||||
syscon = <&slcr>;
|
||||
};
|
||||
|
||||
pinctrl0: pinctrl@700 {
|
||||
compatible = "xlnx,pinctrl-zynq";
|
||||
reg = <0x700 0x200>;
|
||||
syscon = <&slcr>;
|
||||
};
|
||||
};
|
||||
|
||||
dmac_s: dmac@f8003000 {
|
||||
compatible = "arm,pl330", "arm,primecell";
|
||||
reg = <0xf8003000 0x1000>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupt-names = "abort", "dma0", "dma1", "dma2", "dma3",
|
||||
"dma4", "dma5", "dma6", "dma7";
|
||||
interrupts = <0 13 4>,
|
||||
<0 14 4>, <0 15 4>,
|
||||
<0 16 4>, <0 17 4>,
|
||||
<0 40 4>, <0 41 4>,
|
||||
<0 42 4>, <0 43 4>;
|
||||
#dma-cells = <1>;
|
||||
#dma-channels = <8>;
|
||||
#dma-requests = <4>;
|
||||
clocks = <&clkc 27>;
|
||||
clock-names = "apb_pclk";
|
||||
};
|
||||
|
||||
devcfg: devcfg@f8007000 {
|
||||
compatible = "xlnx,zynq-devcfg-1.0";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 8 4>;
|
||||
reg = <0xf8007000 0x100>;
|
||||
clocks = <&clkc 12>, <&clkc 15>, <&clkc 16>, <&clkc 17>, <&clkc 18>;
|
||||
clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3";
|
||||
syscon = <&slcr>;
|
||||
};
|
||||
|
||||
efuse: efuse@f800d000 {
|
||||
compatible = "xlnx,zynq-efuse";
|
||||
reg = <0xf800d000 0x20>;
|
||||
};
|
||||
|
||||
global_timer: timer@f8f00200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0xf8f00200 0x20>;
|
||||
interrupts = <1 11 0x301>;
|
||||
interrupt-parent = <&intc>;
|
||||
clocks = <&clkc 4>;
|
||||
};
|
||||
|
||||
ttc0: timer@f8001000 {
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 10 4>, <0 11 4>, <0 12 4>;
|
||||
compatible = "cdns,ttc";
|
||||
clocks = <&clkc 6>;
|
||||
reg = <0xF8001000 0x1000>;
|
||||
};
|
||||
|
||||
ttc1: timer@f8002000 {
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 37 4>, <0 38 4>, <0 39 4>;
|
||||
compatible = "cdns,ttc";
|
||||
clocks = <&clkc 6>;
|
||||
reg = <0xF8002000 0x1000>;
|
||||
};
|
||||
|
||||
scutimer: timer@f8f00600 {
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <1 13 0x301>;
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0xf8f00600 0x20>;
|
||||
clocks = <&clkc 4>;
|
||||
};
|
||||
|
||||
usb0: usb@e0002000 {
|
||||
compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 28>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 21 4>;
|
||||
reg = <0xe0002000 0x1000>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
usb1: usb@e0003000 {
|
||||
compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
|
||||
status = "disabled";
|
||||
clocks = <&clkc 29>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 44 4>;
|
||||
reg = <0xe0003000 0x1000>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
watchdog0: watchdog@f8005000 {
|
||||
clocks = <&clkc 45>;
|
||||
compatible = "cdns,wdt-r1p2";
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <0 9 1>;
|
||||
reg = <0xf8005000 0x1000>;
|
||||
timeout-sec = <10>;
|
||||
};
|
||||
|
||||
etb@f8801000 {
|
||||
compatible = "arm,coresight-etb10", "arm,primecell";
|
||||
reg = <0xf8801000 0x1000>;
|
||||
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
|
||||
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
|
||||
in-ports {
|
||||
port {
|
||||
etb_in_port: endpoint {
|
||||
remote-endpoint = <&replicator_out_port1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
tpiu@f8803000 {
|
||||
compatible = "arm,coresight-tpiu", "arm,primecell";
|
||||
reg = <0xf8803000 0x1000>;
|
||||
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
|
||||
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
|
||||
in-ports {
|
||||
port {
|
||||
tpiu_in_port: endpoint {
|
||||
remote-endpoint = <&replicator_out_port0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
funnel@f8804000 {
|
||||
compatible = "arm,coresight-static-funnel", "arm,primecell";
|
||||
reg = <0xf8804000 0x1000>;
|
||||
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
|
||||
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
|
||||
|
||||
/* funnel output ports */
|
||||
out-ports {
|
||||
port {
|
||||
funnel_out_port: endpoint {
|
||||
remote-endpoint =
|
||||
<&replicator_in_port0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* funnel input ports */
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
funnel0_in_port0: endpoint {
|
||||
remote-endpoint = <&ptm0_out_port>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
funnel0_in_port1: endpoint {
|
||||
remote-endpoint = <&ptm1_out_port>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
funnel0_in_port2: endpoint {
|
||||
};
|
||||
};
|
||||
/* The other input ports are not connect to anything */
|
||||
};
|
||||
};
|
||||
|
||||
ptm@f889c000 {
|
||||
compatible = "arm,coresight-etm3x", "arm,primecell";
|
||||
reg = <0xf889c000 0x1000>;
|
||||
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
|
||||
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
|
||||
cpu = <&cpu0>;
|
||||
out-ports {
|
||||
port {
|
||||
ptm0_out_port: endpoint {
|
||||
remote-endpoint = <&funnel0_in_port0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ptm@f889d000 {
|
||||
compatible = "arm,coresight-etm3x", "arm,primecell";
|
||||
reg = <0xf889d000 0x1000>;
|
||||
clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
|
||||
clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
|
||||
cpu = <&cpu1>;
|
||||
out-ports {
|
||||
port {
|
||||
ptm1_out_port: endpoint {
|
||||
remote-endpoint = <&funnel0_in_port1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
263
examples/zynq7000/SW/devicetree/zynq-pl-remoteport.dtsi
Normal file
263
examples/zynq7000/SW/devicetree/zynq-pl-remoteport.dtsi
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Zynq 7000 PL Interface over Remote-port.
|
||||
*
|
||||
* Copyright (c) 2016, Xilinx Inc
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the <organization> nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
&slcr {
|
||||
/* In QEMU, the SLCR exports GPIOS (e.g the FPGA Resets). */
|
||||
#gpio-cells = <1>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
/* Append stuff to the PS nodes. */
|
||||
/ {
|
||||
/* This version of the AMBA PL describes the PS/PL interface
|
||||
* and not the devices that are available on the PL side.
|
||||
*
|
||||
* This is what QEMU will use to instantiate the RemotePort
|
||||
* connections allowing for cosimulation.
|
||||
*/
|
||||
amba_pl {
|
||||
cosim_rp_0: cosim@0 {
|
||||
compatible = "remote-port";
|
||||
sync = <1>;
|
||||
chrdev-id = "pl-rp";
|
||||
};
|
||||
|
||||
m_axi_gp0: rp_m_axi_gp0@40000000 {
|
||||
compatible = "remote-port-memory-master";
|
||||
remote-ports = < &cosim_rp_0 7 >;
|
||||
reg = < 0x40000000 0x40000000 >;
|
||||
};
|
||||
|
||||
m_axi_gp1: rp_m_axi_gp1@80000000 {
|
||||
compatible = "remote-port-memory-master";
|
||||
remote-ports = < &cosim_rp_0 8 >;
|
||||
reg = < 0x80000000 0x40000000 >;
|
||||
};
|
||||
|
||||
s_axi_gp0: rp_s_axi_gp0@0 {
|
||||
compatible = "remote-port-memory-slave";
|
||||
remote-ports = < &cosim_rp_0 0 >;
|
||||
};
|
||||
s_axi_gp1: rp_s_axi_gp1@0 {
|
||||
compatible = "remote-port-memory-slave";
|
||||
remote-ports = < &cosim_rp_0 1 >;
|
||||
};
|
||||
afi_0: rp_afi0@0 {
|
||||
compatible = "remote-port-memory-slave";
|
||||
remote-ports = < &cosim_rp_0 2 >;
|
||||
};
|
||||
afi_1: rp_afi1@0 {
|
||||
compatible = "remote-port-memory-slave";
|
||||
remote-ports = < &cosim_rp_0 3 >;
|
||||
};
|
||||
afi_2: rp_afi2@0 {
|
||||
compatible = "remote-port-memory-slave";
|
||||
remote-ports = < &cosim_rp_0 4 >;
|
||||
};
|
||||
afi_3: rp_afi3@0 {
|
||||
compatible = "remote-port-memory-slave";
|
||||
remote-ports = < &cosim_rp_0 5 >;
|
||||
};
|
||||
acp: rp_acp0@0 {
|
||||
compatible = "remote-port-memory-slave";
|
||||
remote-ports = < &cosim_rp_0 6 >;
|
||||
};
|
||||
|
||||
wires_in: rp_wires_in@0 {
|
||||
compatible = "remote-port-gpio";
|
||||
remote-ports = < &cosim_rp_0 9 >;
|
||||
num-gpios = < 16 >;
|
||||
/* QEMU has a bug in the interrupts-extended parsing,
|
||||
* so we need to use interrupt-parent for the moment.
|
||||
*/
|
||||
interrupt-parent = < &intc >;
|
||||
interrupts = <
|
||||
0x0 29 0x4
|
||||
0x0 30 0x4
|
||||
0x0 31 0x4
|
||||
0x0 32 0x4
|
||||
0x0 33 0x4
|
||||
0x0 34 0x4
|
||||
0x0 35 0x4
|
||||
0x0 36 0x4
|
||||
|
||||
0x0 52 0x4
|
||||
0x0 53 0x4
|
||||
0x0 54 0x4
|
||||
0x0 55 0x4
|
||||
0x0 56 0x4
|
||||
0x0 57 0x4
|
||||
0x0 58 0x4
|
||||
0x0 59 0x4
|
||||
>;
|
||||
};
|
||||
|
||||
wires_out: rp_wires_out@0 {
|
||||
compatible = "remote-port-gpio";
|
||||
remote-ports = < &cosim_rp_0 10 >;
|
||||
num-gpios = <17>;
|
||||
gpios = <
|
||||
/* 17 FPGA_OUT_RESETS. */
|
||||
&slcr 2 &slcr 3 &slcr 4 &slcr 5
|
||||
&slcr 6 &slcr 7 &slcr 8 &slcr 9
|
||||
&slcr 10 &slcr 11 &slcr 12 &slcr 13
|
||||
&slcr 14 &slcr 15 &slcr 16 &slcr 17
|
||||
&slcr 18
|
||||
>;
|
||||
};
|
||||
|
||||
rp_cosim_intr_pstopl: rp_cosim_intr_pstopl@0 {
|
||||
#interrupt-cells = <3>;
|
||||
interrupt-controller;
|
||||
compatible = "remote-port-gpio";
|
||||
remote-ports = <&cosim_rp_0 11>;
|
||||
/* There are only 28 connections but due to the offset we need
|
||||
* a higher number here.
|
||||
*/
|
||||
num-gpios = <96>;
|
||||
cell-offset-irq-num = <1>;
|
||||
};
|
||||
|
||||
/* This area can be used for implentation specific emulation*/
|
||||
rp_cosim_reserved: rp_cosim_reserved@0{
|
||||
compatible = "remote-port-memory-master";
|
||||
remote-ports = <&cosim_rp_0 12>;
|
||||
reg = <0xFE000000 0x100000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&can1 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 0 4>, <0 0 0 &intc 0 51 4>;
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 1 4>, <0 0 0 &intc 0 50 4>;
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 2 4>, <0 0 0 &intc 0 49 4>;
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 3 4>, <0 0 0 &intc 0 48 4>;
|
||||
};
|
||||
|
||||
&sdhci1 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 4 4>, <0 0 0 &intc 0 47 4>;
|
||||
};
|
||||
|
||||
&gem1 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 6 4>, <0 0 0 &intc 0 45 4>;
|
||||
};
|
||||
|
||||
&usb1 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 7 4>, <0 0 0 &intc 0 44 4>;
|
||||
};
|
||||
|
||||
&can0 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 8 4>, <0 0 0 &intc 0 28 4>;
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 10 4>, <0 0 0 &intc 0 26 4>;
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 11 4>, <0 0 0 &intc 0 25 4>;
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 12 4>, <0 0 0 &intc 0 24 4>;
|
||||
};
|
||||
|
||||
&gem0 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 14 4>, <0 0 0 &intc 0 22 4>;
|
||||
};
|
||||
|
||||
&usb0 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 15 4>, <0 0 0 &intc 0 21 4>;
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 16 4>, <0 0 0 &intc 0 20 4>;
|
||||
};
|
||||
|
||||
&qspi {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 18 4>, <0 0 0 &intc 0 19 4>;
|
||||
};
|
||||
|
||||
&smcc {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 19 4>, <0 0 0 &intc 0 18 4>;
|
||||
};
|
||||
|
||||
&dmac_s {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 &rp_cosim_intr_pstopl 0 28 4>, <0 0 0 &intc 0 13 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 20 4>, <0 0 0 &intc 0 14 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 21 4>, <0 0 0 &intc 0 15 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 22 4>, <0 0 0 &intc 0 16 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 23 4>, <0 0 0 &intc 0 17 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 24 4>, <0 0 0 &intc 0 40 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 25 4>, <0 0 0 &intc 0 41 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 26 4>, <0 0 0 &intc 0 42 4>,
|
||||
<0 0 0 &rp_cosim_intr_pstopl 0 27 4>, <0 0 0 &intc 0 43 4>;
|
||||
};
|
89
examples/zynq7000/SW/linker.ld
Normal file
89
examples/zynq7000/SW/linker.ld
Normal file
@ -0,0 +1,89 @@
|
||||
OUTPUT_FORMAT ("elf32-littlearm")
|
||||
|
||||
MEMORY
|
||||
{
|
||||
SRAM_0 : ORIGIN = 0x00000000, LENGTH = 0x00030000 /* 192k */
|
||||
SRAM_1 : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000 /* 64k */
|
||||
DDR_PS : ORIGIN = 0x00100000, LENGTH = 0x0FF00000 /* 256M */
|
||||
}
|
||||
|
||||
EXTERN(__stack_size);
|
||||
ASSERT(__stack_size, "Must provide a non-zero stack size");
|
||||
|
||||
EXTERN(_start);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.text :
|
||||
{
|
||||
__stext = .;
|
||||
*(.vectortable) /* Vector table */
|
||||
*(.text .text.*) /* Standard Code */
|
||||
*(.rodata .rodata.*) /* Constants, strings, ... */
|
||||
*(.glue_7) /* Glue ARM to thumb code */
|
||||
*(.glue_7t) /* Glue thumb to ARM code */
|
||||
__etext = .;
|
||||
} >DDR_PS
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__sdata = .;
|
||||
*(.data .data.*)
|
||||
__edata = .;
|
||||
|
||||
} >DDR_PS
|
||||
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .; /* Used for zeroing bss on startup */
|
||||
*(.bss .bss.*)
|
||||
__bss_end__ = .;
|
||||
} >DDR_PS
|
||||
|
||||
. = ALIGN(4);
|
||||
end = .;
|
||||
|
||||
/* Place all stacks in SRAM_1 - need to avoid filling addresses */
|
||||
/* 0xfffffe00 to 0xfffffff0 - proc1 is halted running code in this range */
|
||||
/* TODO: assert stacks do not step on proc1's code out of reset */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
. += __stack_size;
|
||||
__proc0_irq_stack = .;
|
||||
. += __stack_size;
|
||||
__proc0_fiq_stack = .;
|
||||
. += __stack_size;
|
||||
__proc0_svc_stack = .;
|
||||
. += __stack_size;
|
||||
__proc0_abt_stack = .;
|
||||
. += __stack_size;
|
||||
__proc0_und_stack = .;
|
||||
. += __stack_size;
|
||||
__proc0_sys_stack = .;
|
||||
. += __stack_size;
|
||||
__proc1_irq_stack = .;
|
||||
. += __stack_size;
|
||||
__proc1_fiq_stack = .;
|
||||
. += __stack_size;
|
||||
__proc1_svc_stack = .;
|
||||
. += __stack_size;
|
||||
__proc1_abt_stack = .;
|
||||
. += __stack_size;
|
||||
__proc1_und_stack = .;
|
||||
. += __stack_size;
|
||||
__proc1_sys_stack = .;
|
||||
. += __stack_size;
|
||||
} >SRAM_1
|
||||
|
||||
.data.ddr :
|
||||
{
|
||||
*(.data_in_ddr)
|
||||
} >DDR_PS
|
||||
|
||||
.note.gnu.build-id : {
|
||||
KEEP (*(.note.gnu.build-id))
|
||||
} >DDR_PS
|
||||
}
|
96
examples/zynq7000/SW/src/boot.S
Normal file
96
examples/zynq7000/SW/src/boot.S
Normal file
@ -0,0 +1,96 @@
|
||||
.syntax unified /* Use the unified instruction syntax */
|
||||
.arm /* Assemble ARM instruction set, not thumb */
|
||||
|
||||
.equ PROC1_RESET_VECTOR_TABLE, 0xFFFFFFF0
|
||||
|
||||
.equ CPSR_MODE_USER, 0x10
|
||||
.equ CPSR_MODE_FIQ, 0x11
|
||||
.equ CPSR_MODE_IRQ, 0x12
|
||||
.equ CPSR_MODE_SVC, 0x13
|
||||
.equ CPSR_MODE_ABORT, 0x17
|
||||
.equ CPSR_MODE_UNDEFINED, 0x8B
|
||||
.equ CPSR_MODE_SYSTEM, 0x1F
|
||||
|
||||
.equ CPSR_IRQ, 0x80 /* disable IRQ interrupts */
|
||||
.equ CPSR_FIQ, 0x40 /* disable FIQ interrupts */
|
||||
|
||||
.global __stack_size
|
||||
.equ __stack_size, 0x1000
|
||||
|
||||
// ------------------
|
||||
.section .vectortable
|
||||
// ------------------
|
||||
.global vectortable
|
||||
vectortable:
|
||||
/* Exception Processor Mode Event Return Sequence */
|
||||
b reset_handler /* MODE_SVC System Reset n/a */
|
||||
b undef_handler /* MODE_UNDEFINED Undefined Instruction MOVS PC, LR (if emulating) */
|
||||
b SVC_handler /* MODE_SVC SVC instruction MOVS PC, LR */
|
||||
b prefetch_abort_handler /* MODE_ABORT Invalid inst. address SUBS PC, LR, #4 */
|
||||
b data_abort_handler /* MODE_ABORT R/W to invalid address SUBS PC, LR, #8 (to retry) */
|
||||
b hypervisor_handler /* MODE_HYP Hypervisor entry ERET */
|
||||
b IRQ_handler /* MODE_IRQ IRQ Input Asserted SUBS PC, LR, #4 */
|
||||
b FIQ_handler /* MODE_FIQ FIQ Input Asserted SUBS PC, LR, #4 */
|
||||
|
||||
reset_handler:
|
||||
b _start
|
||||
|
||||
undef_handler:
|
||||
b .
|
||||
|
||||
SVC_handler:
|
||||
b .
|
||||
|
||||
prefetch_abort_handler:
|
||||
b .
|
||||
|
||||
data_abort_handler:
|
||||
b .
|
||||
|
||||
hypervisor_handler:
|
||||
b .
|
||||
|
||||
IRQ_handler:
|
||||
b .
|
||||
|
||||
FIQ_handler:
|
||||
b .
|
||||
|
||||
// -----------
|
||||
.section .text
|
||||
// -----------
|
||||
.global _start
|
||||
_start:
|
||||
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_IRQ) /* switch to MODE_IRQ */
|
||||
ldr sp, =__proc0_irq_stack /* load IRQ mode stack pointer */
|
||||
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_FIQ) /* switch to MODE_FIQ */
|
||||
ldr sp, =__proc0_fiq_stack /* load FIQ mode stack pointer */
|
||||
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_ABORT) /* switch to MODE_ABT */
|
||||
ldr sp, =__proc0_abt_stack /* load ABT mode stack pointer */
|
||||
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_UNDEFINED) /* switch to MODE_UND */
|
||||
ldr sp, =__proc0_und_stack /* load UND mode stack pointer */
|
||||
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_SYSTEM) /* switch to MODE_SYS */
|
||||
ldr sp, =__proc0_sys_stack /* load SYS mode stack pointer */
|
||||
msr CPSR, #(CPSR_IRQ | CPSR_FIQ | CPSR_MODE_SVC) /* switch to MODE_SVC */
|
||||
ldr sp, =__proc0_svc_stack /* load SVC mode stack pointer */
|
||||
/* We are now in SVC mode */
|
||||
|
||||
// Disable L1 cache
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 // Invalidate cache
|
||||
mcr p15, 0, r0, c8, c7, 0 // Invalidate tlb
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #0x1000
|
||||
bic r0, r0, #0x0004
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
/* Set vector table base address */
|
||||
ldr r0, =vectortable
|
||||
mcr p15, #0, r0, c12, c0, #0
|
||||
|
||||
b main
|
||||
|
||||
_hang:
|
||||
b _hang
|
||||
|
||||
.end
|
30
examples/zynq7000/SW/src/main.c
Normal file
30
examples/zynq7000/SW/src/main.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include "ps7_init.h"
|
||||
#include "zynq.h"
|
||||
#include "uart.h"
|
||||
#include "printf.h"
|
||||
|
||||
// COSIM control
|
||||
volatile unsigned int * PAUSE = (unsigned int*) 0x7ffffff4; // Pause the cosimulation
|
||||
volatile unsigned int * SOS = (unsigned int*) 0x7ffffff8; // (Re)start the cosimulation
|
||||
volatile unsigned int * EOS = (unsigned int*) 0x7ffffffc; // Stop the cosimulation
|
||||
|
||||
|
||||
void main(){
|
||||
cpu_disable_interrups();
|
||||
// Initialize ZYNQ Processing System
|
||||
// ps7_init();
|
||||
// Start UART
|
||||
uart_setup();
|
||||
|
||||
*SOS = 1;
|
||||
|
||||
printf("Hello World!\n");
|
||||
|
||||
for(int i=0; i<32; i++){
|
||||
printf("i=%d\n", i);
|
||||
}
|
||||
|
||||
*EOS = 1;
|
||||
|
||||
for(;;);
|
||||
}
|
452
examples/zynq7000/SW/src/printf.c
Normal file
452
examples/zynq7000/SW/src/printf.c
Normal file
@ -0,0 +1,452 @@
|
||||
#include "printf.h"
|
||||
#include "uart.h"
|
||||
|
||||
#define NULL 0
|
||||
|
||||
extern int putchar(int c);
|
||||
static void print_double_float(double val, unsigned int precision);
|
||||
|
||||
static void simple_outputchar(char **str, char c)
|
||||
{
|
||||
if (str) {
|
||||
**str = c;
|
||||
++(*str);
|
||||
} else {
|
||||
uart_send(c);
|
||||
}
|
||||
}
|
||||
|
||||
enum flags {
|
||||
PAD_ZERO = 1,
|
||||
PAD_RIGHT = 2,
|
||||
};
|
||||
|
||||
static int prints(char **out, const char *string, int width, int flags)
|
||||
{
|
||||
int pc = 0, padchar = ' ';
|
||||
|
||||
if (width > 0) {
|
||||
int len = 0;
|
||||
const char *ptr;
|
||||
for (ptr = string; *ptr; ++ptr) ++len;
|
||||
if (len >= width) width = 0;
|
||||
else width -= len;
|
||||
if (flags & PAD_ZERO)
|
||||
padchar = '0';
|
||||
}
|
||||
if (!(flags & PAD_RIGHT)) {
|
||||
for ( ; width > 0; --width) {
|
||||
simple_outputchar(out, padchar);
|
||||
++pc;
|
||||
}
|
||||
}
|
||||
for ( ; *string ; ++string) {
|
||||
simple_outputchar(out, *string);
|
||||
++pc;
|
||||
}
|
||||
for ( ; width > 0; --width) {
|
||||
simple_outputchar(out, padchar);
|
||||
++pc;
|
||||
}
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
#define PRINT_BUF_LEN 64
|
||||
|
||||
static int simple_outputi(char **out, long long i, int base, int sign, int width, int flags, int letbase)
|
||||
{
|
||||
char print_buf[PRINT_BUF_LEN];
|
||||
char *s;
|
||||
int t, neg = 0, pc = 0;
|
||||
unsigned long long u = i;
|
||||
|
||||
if (i == 0) {
|
||||
print_buf[0] = '0';
|
||||
print_buf[1] = '\0';
|
||||
return prints(out, print_buf, width, flags);
|
||||
}
|
||||
|
||||
if (sign && base == 10 && i < 0) {
|
||||
neg = 1;
|
||||
u = -i;
|
||||
}
|
||||
|
||||
s = print_buf + PRINT_BUF_LEN-1;
|
||||
*s = '\0';
|
||||
|
||||
while (u) {
|
||||
t = u % base;
|
||||
if( t >= 10 )
|
||||
t += letbase - '0' - 10;
|
||||
*--s = t + '0';
|
||||
u /= base;
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
if( width && (flags & PAD_ZERO) ) {
|
||||
simple_outputchar (out, '-');
|
||||
++pc;
|
||||
--width;
|
||||
}
|
||||
else {
|
||||
*--s = '-';
|
||||
}
|
||||
}
|
||||
|
||||
return pc + prints (out, s, width, flags);
|
||||
}
|
||||
|
||||
|
||||
static int simple_vsprintf(char **out, char *format, va_list ap)
|
||||
{
|
||||
int width, flags;
|
||||
int pc = 0;
|
||||
char scr[2];
|
||||
union {
|
||||
char c;
|
||||
char *s;
|
||||
int i;
|
||||
unsigned int u;
|
||||
long li;
|
||||
unsigned long lu;
|
||||
long long lli;
|
||||
unsigned long long llu;
|
||||
short hi;
|
||||
unsigned short hu;
|
||||
signed char hhi;
|
||||
unsigned char hhu;
|
||||
void *p;
|
||||
double d;
|
||||
} u;
|
||||
|
||||
for (; *format != 0; ++format) {
|
||||
if (*format == '%') {
|
||||
++format;
|
||||
width = flags = 0;
|
||||
if (*format == '\0')
|
||||
break;
|
||||
if (*format == '%')
|
||||
goto out;
|
||||
if (*format == '-') {
|
||||
++format;
|
||||
flags = PAD_RIGHT;
|
||||
}
|
||||
while (*format == '0') {
|
||||
++format;
|
||||
flags |= PAD_ZERO;
|
||||
}
|
||||
if (*format == '*') {
|
||||
width = va_arg(ap, int);
|
||||
format++;
|
||||
} else {
|
||||
for ( ; *format >= '0' && *format <= '9'; ++format) {
|
||||
width *= 10;
|
||||
width += *format - '0';
|
||||
}
|
||||
}
|
||||
switch (*format) {
|
||||
case('d'):
|
||||
u.i = va_arg(ap, int);
|
||||
pc += simple_outputi(out, u.i, 10, 1, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('u'):
|
||||
u.u = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.u, 10, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('x'):
|
||||
u.u = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.u, 16, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('X'):
|
||||
u.u = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.u, 16, 0, width, flags, 'A');
|
||||
break;
|
||||
|
||||
case('c'):
|
||||
u.c = va_arg(ap, int);
|
||||
scr[0] = u.c;
|
||||
scr[1] = '\0';
|
||||
pc += prints(out, scr, width, flags);
|
||||
break;
|
||||
|
||||
case('f'):
|
||||
u.d = va_arg(ap, double);
|
||||
print_double_float(u.d, width);
|
||||
break;
|
||||
|
||||
case('s'):
|
||||
u.s = va_arg(ap, char *);
|
||||
pc += prints(out, u.s ? u.s : "(null)", width, flags);
|
||||
break;
|
||||
case('l'):
|
||||
++format;
|
||||
switch (*format) {
|
||||
case('d'):
|
||||
u.li = va_arg(ap, long);
|
||||
pc += simple_outputi(out, u.li, 10, 1, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('u'):
|
||||
u.lu = va_arg(ap, unsigned long);
|
||||
pc += simple_outputi(out, u.lu, 10, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('x'):
|
||||
u.lu = va_arg(ap, unsigned long);
|
||||
pc += simple_outputi(out, u.lu, 16, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('X'):
|
||||
u.lu = va_arg(ap, unsigned long);
|
||||
pc += simple_outputi(out, u.lu, 16, 0, width, flags, 'A');
|
||||
break;
|
||||
|
||||
case('l'):
|
||||
++format;
|
||||
switch (*format) {
|
||||
case('d'):
|
||||
u.lli = va_arg(ap, long long);
|
||||
pc += simple_outputi(out, u.lli, 10, 1, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('u'):
|
||||
u.llu = va_arg(ap, unsigned long long);
|
||||
pc += simple_outputi(out, u.llu, 10, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('x'):
|
||||
u.llu = va_arg(ap, unsigned long long);
|
||||
pc += simple_outputi(out, u.llu, 16, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('X'):
|
||||
u.llu = va_arg(ap, unsigned long long);
|
||||
pc += simple_outputi(out, u.llu, 16, 0, width, flags, 'A');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case('h'):
|
||||
++format;
|
||||
switch (*format) {
|
||||
case('d'):
|
||||
u.hi = va_arg(ap, int);
|
||||
pc += simple_outputi(out, u.hi, 10, 1, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('u'):
|
||||
u.hu = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.lli, 10, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('x'):
|
||||
u.hu = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('X'):
|
||||
u.hu = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'A');
|
||||
break;
|
||||
|
||||
case('h'):
|
||||
++format;
|
||||
switch (*format) {
|
||||
case('d'):
|
||||
u.hhi = va_arg(ap, int);
|
||||
pc += simple_outputi(out, u.hhi, 10, 1, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('u'):
|
||||
u.hhu = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.lli, 10, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('x'):
|
||||
u.hhu = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'a');
|
||||
break;
|
||||
|
||||
case('X'):
|
||||
u.hhu = va_arg(ap, unsigned int);
|
||||
pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'A');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
out:
|
||||
simple_outputchar (out, *format);
|
||||
++pc;
|
||||
}
|
||||
}
|
||||
if (out) **out = '\0';
|
||||
return pc;
|
||||
}
|
||||
|
||||
int printf(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, fmt);
|
||||
r = simple_vsprintf(NULL, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sprintf(char *buf, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, fmt);
|
||||
r = simple_vsprintf(&buf, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void hexDump (const char * desc, const void * addr, const int len) {
|
||||
int i;
|
||||
unsigned char buff[17];
|
||||
const unsigned char * pc = (const unsigned char *)addr;
|
||||
|
||||
// Output description if given.
|
||||
|
||||
if (desc != NULL)
|
||||
printf ("%s:\n", desc);
|
||||
|
||||
// Length checks.
|
||||
|
||||
if (len == 0) {
|
||||
printf(" ZERO LENGTH\n");
|
||||
return;
|
||||
}
|
||||
else if (len < 0) {
|
||||
printf(" NEGATIVE LENGTH: %d\n", len);
|
||||
return;
|
||||
}
|
||||
|
||||
// Process every byte in the data.
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
// Multiple of 16 means new line (with line offset).
|
||||
|
||||
if ((i % 16) == 0) {
|
||||
// Don't print ASCII buffer for the "zeroth" line.
|
||||
|
||||
if (i != 0)
|
||||
printf (" %s\n", buff);
|
||||
|
||||
// Output the offset.
|
||||
|
||||
printf (" %04x ", i);
|
||||
}
|
||||
|
||||
// Now the hex code for the specific character.
|
||||
printf (" %02x", pc[i]);
|
||||
|
||||
// And buffer a printable ASCII character for later.
|
||||
|
||||
if ((pc[i] < 0x20) || (pc[i] > 0x7e)) // isprint() may be better.
|
||||
buff[i % 16] = '.';
|
||||
else
|
||||
buff[i % 16] = pc[i];
|
||||
buff[(i % 16) + 1] = '\0';
|
||||
}
|
||||
|
||||
// Pad out last line if not exactly 16 characters.
|
||||
|
||||
while ((i % 16) != 0) {
|
||||
printf (" ");
|
||||
i++;
|
||||
}
|
||||
|
||||
// And print the final ASCII buffer.
|
||||
|
||||
printf (" %s\n", buff);
|
||||
}
|
||||
|
||||
#define MAX_PRECISION 50
|
||||
|
||||
#define IsNaN(n) (n != n)
|
||||
|
||||
// %f: double/single precision support (double or promoted float, 64-bits)
|
||||
static void print_double_float(double val, unsigned int precision)
|
||||
{
|
||||
unsigned int cur_prec = 1;
|
||||
if(precision==0)
|
||||
precision = MAX_PRECISION;
|
||||
|
||||
// if the user-defined precision is out-of-bounds, normalize it
|
||||
if(precision > MAX_PRECISION)
|
||||
precision = MAX_PRECISION;
|
||||
|
||||
// if it's negative, show it!
|
||||
if(val < 0)
|
||||
{
|
||||
printf("-");
|
||||
|
||||
// change to a positive value
|
||||
val = -val;
|
||||
}
|
||||
|
||||
// check to see if it is Not-a-Number
|
||||
if(IsNaN(val))
|
||||
{
|
||||
printf("NaN");
|
||||
return;
|
||||
}
|
||||
|
||||
// print the integer part of the floating point
|
||||
printf("%d", (int)val);
|
||||
|
||||
// if precision == 0, only print the integer part
|
||||
if(!precision)
|
||||
return;
|
||||
|
||||
// now on to the decimal potion
|
||||
printf(".");
|
||||
|
||||
// remove the integer part
|
||||
val -= (double)((int)val);
|
||||
|
||||
/* on every iteration, make sure there are still decimal places left that are non-zero,
|
||||
and make sure we're still within the user-defined precision range. */
|
||||
while(val > (double)((int)val) && cur_prec++ < precision+1)
|
||||
{
|
||||
// move the next decimal into the integer portion and print it
|
||||
val *= 10;
|
||||
printf("%d", (int)val);
|
||||
|
||||
/* if the value is == the floored value (integer portion),
|
||||
then there are no more decimal places that are non-zero. */
|
||||
if(val == (double)((int)val))
|
||||
return;
|
||||
|
||||
// subtract the integer portion
|
||||
val -= (double)((int)val);
|
||||
}
|
||||
}
|
11
examples/zynq7000/SW/src/printf.h
Normal file
11
examples/zynq7000/SW/src/printf.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __H_KPRINTF
|
||||
#define __H_KPRINTF 1
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
int printf(char * fmt, ...);
|
||||
int sprintf(char * buf, char * fmt, ...);
|
||||
|
||||
void hexDump (const char * desc, const void * addr, const int len);
|
||||
|
||||
#endif
|
105
examples/zynq7000/SW/src/uart.c
Normal file
105
examples/zynq7000/SW/src/uart.c
Normal file
@ -0,0 +1,105 @@
|
||||
#include "uart.h"
|
||||
#include "stdint.h"
|
||||
|
||||
#define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */
|
||||
#define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */
|
||||
|
||||
#define XUARTPS_CR_OFFSET 0x0000U /**< Control Register [8:0] */
|
||||
#define XUARTPS_MR_OFFSET 0x0004U /**< Mode Register [9:0] */
|
||||
#define XUARTPS_BAUDGEN_OFFSET 0x0018U /**< Baud Rate Generator [15:0] */
|
||||
#define XUARTPS_BAUDDIV_OFFSET 0x0034U /**< Baud Rate Divider [7:0] */
|
||||
#define XUARTPS_FIFO_OFFSET 0x0030U /**< FIFO [7:0] */
|
||||
#define XUARTPS_SR_OFFSET 0x002CU /**< Channel Status [14:0] */
|
||||
#define XPS_UART1_BASEADDR 0xE0001000U
|
||||
|
||||
#define XUARTPS_MR_CHMODE_NORM 0x00000000U /**< Normal mode */
|
||||
#define XUARTPS_MR_STOPMODE_1_BIT 0x00000000U /**< 1 stop bit */
|
||||
#define XUARTPS_MR_PARITY_NONE 0x00000020U /**< No parity mode */
|
||||
#define XUARTPS_MR_CHARLEN_8_BIT 0x00000000U /**< 8 bits data */
|
||||
#define XUARTPS_MR_CLKSEL 0x00000001U /**< Input clock selection */
|
||||
|
||||
#define XUARTPS_SR_TNFUL 0x00004000U /**< TX FIFO Nearly Full Status */
|
||||
#define XUARTPS_SR_TACTIVE 0x00000800U /**< TX active */
|
||||
#define XUARTPS_SR_RXEMPTY 0x00000002U /**< RX FIFO empty */
|
||||
|
||||
#define XUARTPS_CR_TX_DIS 0x00000020U /**< TX disabled. */
|
||||
#define XUARTPS_CR_TX_EN 0x00000010U /**< TX enabled */
|
||||
#define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */
|
||||
#define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */
|
||||
|
||||
#define POINTER_TO_REGISTER(REG) ( *((volatile uint32_t*)(REG)))
|
||||
|
||||
#define UART_BASE XPS_UART1_BASEADDR
|
||||
#define UART_CTRL POINTER_TO_REGISTER(UART_BASE + XUARTPS_CR_OFFSET) // Control Register
|
||||
#define UART_MODE POINTER_TO_REGISTER(UART_BASE + XUARTPS_MR_OFFSET) // Mode Register
|
||||
|
||||
#define UART_BAUD_GEN POINTER_TO_REGISTER(UART_BASE + XUARTPS_BAUDGEN_OFFSET) // Baud Rate Generator "CD"
|
||||
#define UART_BAUD_DIV POINTER_TO_REGISTER(UART_BASE + XUARTPS_BAUDDIV_OFFSET) // Baud Rate Divider "BDIV"
|
||||
#define UART_FIFO POINTER_TO_REGISTER(UART_BASE + XUARTPS_FIFO_OFFSET) // FIFO
|
||||
#define UART_STATUS POINTER_TO_REGISTER(UART_BASE + XUARTPS_SR_OFFSET) // Channel Status
|
||||
|
||||
#define BUFLEN 127
|
||||
|
||||
static uint16_t end_ndx;
|
||||
static char buf[BUFLEN+1];
|
||||
#define buf_len ((end_ndx - start_ndx) % BUFLEN)
|
||||
static inline int inc_ndx(int n) { return ((n + 1) % BUFLEN); }
|
||||
static inline int dec_ndx(int n) { return (((n + BUFLEN) - 1) % BUFLEN); }
|
||||
|
||||
void uart_send(char c) {
|
||||
while (UART_STATUS & XUARTPS_SR_TNFUL);
|
||||
UART_FIFO = c;
|
||||
while (UART_STATUS & XUARTPS_SR_TACTIVE);
|
||||
}
|
||||
|
||||
char uart_recv() {
|
||||
if ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY)
|
||||
return 0;
|
||||
|
||||
return UART_FIFO;
|
||||
}
|
||||
|
||||
char uart_recv_blocking() {
|
||||
while ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY);
|
||||
return UART_FIFO;
|
||||
}
|
||||
|
||||
void uart_setup(void) {
|
||||
uint32_t r = 0; // Temporary value variable
|
||||
r = UART_CTRL;
|
||||
r &= ~(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN); // Clear Tx & Rx Enable
|
||||
r |= XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS; // Tx & Rx Disable
|
||||
UART_CTRL = r;
|
||||
|
||||
UART_MODE = 0;
|
||||
UART_MODE &= ~XUARTPS_MR_CLKSEL; // Clear "Input clock selection" - 0: clock source is uart_ref_clk
|
||||
UART_MODE |= XUARTPS_MR_CHARLEN_8_BIT; // Set "8 bits data"
|
||||
UART_MODE |= XUARTPS_MR_PARITY_NONE; // Set "No parity mode"
|
||||
UART_MODE |= XUARTPS_MR_STOPMODE_1_BIT; // Set "1 stop bit"
|
||||
UART_MODE |= XUARTPS_MR_CHMODE_NORM; // Set "Normal mode"
|
||||
|
||||
// baud_rate = sel_clk / (CD * (BDIV + 1) (ref: UG585 - TRM - Ch. 19 UART)
|
||||
UART_BAUD_DIV = 6; // ("BDIV")
|
||||
UART_BAUD_GEN = 124; // ("CD")
|
||||
// Baud Rate = 100Mhz / (124 * (6 + 1)) = 115200 bps
|
||||
|
||||
UART_CTRL |= (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); // TX & RX logic reset
|
||||
|
||||
r = UART_CTRL;
|
||||
r |= XUARTPS_CR_RX_EN | XUARTPS_CR_TX_EN; // Set TX & RX enabled
|
||||
r &= ~(XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS); // Clear TX & RX disabled
|
||||
UART_CTRL = r;
|
||||
}
|
||||
|
||||
void uart_back_up(void){
|
||||
end_ndx = dec_ndx(end_ndx);
|
||||
uart_send('\010');
|
||||
uart_send(' ');
|
||||
uart_send('\010');
|
||||
}
|
||||
|
||||
void uart_puts(char * s){
|
||||
while(*s){
|
||||
uart_send(*(s++));
|
||||
}
|
||||
}
|
11
examples/zynq7000/SW/src/uart.h
Normal file
11
examples/zynq7000/SW/src/uart.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __H_UART
|
||||
#define __H_UART 1
|
||||
|
||||
void uart_send(char c);
|
||||
char uart_recv();
|
||||
char uart_recv_blocking();
|
||||
void uart_setup(void);
|
||||
void uart_back_up(void);
|
||||
void uart_puts(char * s);
|
||||
|
||||
#endif
|
0
examples/zynq7000/SW/src/xil_io.h
Normal file
0
examples/zynq7000/SW/src/xil_io.h
Normal file
33
examples/zynq7000/SW/src/zynq.h
Normal file
33
examples/zynq7000/SW/src/zynq.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef __H_ZYNQ
|
||||
#define __H_ZYNQ 1
|
||||
|
||||
#define ZYNQ_PERIPH_PHY_BASE 0xF8000000
|
||||
|
||||
#define ZYNQ_PERIPH_TTC0_BASE (ZYNQ_PERIPH_PHY_BASE + 0x1000)
|
||||
|
||||
#define ZYNQ_PRI_PERIPH_PHYS_BASE 0xF8F00000
|
||||
#define ZYNQ_PERIPH_SIZE 0x2000
|
||||
|
||||
#define ZYNQ_SCU_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0)
|
||||
#define ZYNQ_SCU_SIZE 0x0100
|
||||
|
||||
#define ZYNQ_GIC_CPU_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x100)
|
||||
#define ZYNQ_GIC_CPU_SIZE 0x0100
|
||||
|
||||
#define ZYNQ_GTIMER_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x200)
|
||||
#define ZYNQ_GTIMER_SIZE 0x0100
|
||||
|
||||
#define ZYNQ_PTIMER_WDT_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x600)
|
||||
#define ZYNQ_PTIMER_WDT_SIZE 0x0100
|
||||
|
||||
#define ZYNQ_GIC_DIST_PHYS_BASE (ZYNQ_PRI_PERIPH_PHYS_BASE + 0x1000)
|
||||
#define ZYNQ_GIC_DIST_SIZE 0x1000
|
||||
|
||||
#define WRITE32(_reg, _val) (*(volatile uint32_t*)&_reg = _val)
|
||||
#define WRITE16(_reg, _val) (*(volatile uint16_t*)&_reg = _val)
|
||||
#define WRITE8(_reg, _val) (*(volatile uint8_t*)&_reg = _val)
|
||||
|
||||
#define cpu_disable_interrups() asm ("cpsid if")
|
||||
#define cpu_enable_interrups() asm ("cpsie if")
|
||||
|
||||
#endif
|
@ -10,6 +10,10 @@ port = 2020
|
||||
privkey = /home/joppe/.ssh/id_rsa
|
||||
pubkey = /home/joppe/.ssh/id_rsa.pub
|
||||
|
||||
# ======================================
|
||||
# BASIC FPGA WORKFLOW
|
||||
# ======================================
|
||||
|
||||
# ######################################
|
||||
# ISE IP block generation
|
||||
[target.ip]
|
||||
@ -91,3 +95,108 @@ files_verilog = OUT/synth/impl_netlist.v
|
||||
#files_xci =
|
||||
files_other = OUT/synth/impl_netlist.sdf
|
||||
# ######################################
|
||||
|
||||
# ======================================
|
||||
# PS/PL workflow
|
||||
# ======================================
|
||||
|
||||
# ######################################
|
||||
# Firmware compilation
|
||||
[target.firmware]
|
||||
toolchain = make
|
||||
|
||||
# Toolchain settings
|
||||
output_files = build/app.elf DISASS
|
||||
buildroot = SW
|
||||
|
||||
# Fileset
|
||||
files_makefile = SW/Makefile
|
||||
files_other = SW/linker.ld
|
||||
SW/src/boot.S
|
||||
SW/src/main.c
|
||||
SW/src/printf.c
|
||||
SW/src/printf.h
|
||||
SW/src/uart.c
|
||||
SW/src/uart.h
|
||||
SW/src/xil_io.h
|
||||
SW/src/zynq.h
|
||||
OUT/ip/zynqps/ps7_init.c
|
||||
OUT/ip/zynqps/ps7_init.h
|
||||
# ######################################
|
||||
|
||||
|
||||
# ######################################
|
||||
# Firmware simulation
|
||||
[target.firmsim]
|
||||
toolchain = qemu
|
||||
|
||||
# Toolchain settings
|
||||
arch = arm
|
||||
machine = xilinx-zynq-a9
|
||||
ram = 256M
|
||||
extra_opts = -serial /dev/null -serial mon:stdio
|
||||
|
||||
# Fileset
|
||||
files_executable = OUT/firmware/app.elf
|
||||
# ######################################
|
||||
|
||||
# ######################################
|
||||
# Device tree compilation
|
||||
[target.devtree]
|
||||
toolchain = make
|
||||
|
||||
# Toolchain settings
|
||||
output_files = system.dtb system.dts
|
||||
buildroot = SW/devicetree
|
||||
|
||||
# Fileset
|
||||
files_makefile = SW/devicetree/Makefile
|
||||
files_other = SW/devicetree/pcw.dtsi
|
||||
SW/devicetree/pl.dtsi
|
||||
SW/devicetree/skeleton.dtsi
|
||||
SW/devicetree/system-top.dts
|
||||
SW/devicetree/zynq-7000.dtsi
|
||||
SW/devicetree/zynq-pl-remoteport.dtsi
|
||||
SW/devicetree/include/dt-bindings/clock/xlnx-versal-clk.h
|
||||
SW/devicetree/include/dt-bindings/power/xlnx-versal-power.h
|
||||
SW/devicetree/include/dt-bindings/reset/xlnx-versal-resets.h
|
||||
# ######################################
|
||||
|
||||
# ######################################
|
||||
# Hardware-firmware cosimulation PS part
|
||||
[target.cosim_ps]
|
||||
toolchain = qemu
|
||||
|
||||
# Toolchain settings
|
||||
arch = xilinxarm
|
||||
machine = arm-generic-fdt-7series
|
||||
ram = 256M
|
||||
extra_opts = -serial /dev/null -serial mon:stdio -dtb ../OUT/devtree/system.dtb \
|
||||
-machine-path /tmp \
|
||||
-icount 1 -sync-quantum 100000 \
|
||||
-device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4
|
||||
|
||||
# Fileset
|
||||
files_executable = OUT/firmware/app.elf
|
||||
files_other = OUT/devtree/system.dtb
|
||||
# ######################################
|
||||
|
||||
# ######################################
|
||||
# Hardware-firmware cosimulation PL part
|
||||
# Note: currently not using xsim since compilation with xilinx
|
||||
# provided tools are horrible on linux
|
||||
[target.cosim_pl]
|
||||
toolchain = questa
|
||||
|
||||
# Toolchain settings
|
||||
toplevel = tb_cosim
|
||||
vcdlevels = 20
|
||||
runtime = all
|
||||
|
||||
# Fileset
|
||||
files_vhdl = RTL/heartbeat.vhd
|
||||
# files_verilog =
|
||||
files_sysverilog = SIM/tb_cosim.sv
|
||||
files_c = SIM/c/remote-port-proto.c SIM/c/cosim.c
|
||||
files_other = SIM/c/remote-port-proto.h
|
||||
# ######################################
|
@ -11,12 +11,16 @@ import shutil
|
||||
def do(config, target, log, subprocesses, prefix='.'):
|
||||
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
|
||||
|
||||
stopafter = config.get(f'target.{target}', 'stopafter', fallback='')
|
||||
|
||||
log("Syntesize:")
|
||||
|
||||
res = xst(config, target, log, subprocesses, prefix)
|
||||
if res != 0:
|
||||
log("ERROR: xst returned with", res)
|
||||
return res
|
||||
if stopafter=='synth':
|
||||
return res
|
||||
|
||||
log("Implement")
|
||||
|
||||
@ -34,6 +38,8 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
if res != 0:
|
||||
log("ERROR: par returned with", res)
|
||||
return res
|
||||
if stopafter=='impl':
|
||||
return res
|
||||
|
||||
log("Generate output files")
|
||||
|
||||
|
83
remotesyn/toolchains/cocotb.py
Normal file
83
remotesyn/toolchains/cocotb.py
Normal file
@ -0,0 +1,83 @@
|
||||
from distutils.command.build import build
|
||||
import shutil
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
def do(config, target, log, subprocesses, prefix='.'):
|
||||
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
|
||||
|
||||
log("Starting cocotb")
|
||||
|
||||
log(" - parsing options")
|
||||
toplevels = config.get(f'target.{target}', 'toplevels', fallback='').split()
|
||||
simulator = config.get(f'target.{target}', 'simulator', fallback='ghdl')
|
||||
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
|
||||
files_python = config.get(f'target.{target}', 'files_python', fallback='').split()
|
||||
files_python_other = config.get(f'target.{target}', 'files_python_other', fallback='').split()
|
||||
files_other = config.get(f'target.{target}', 'files_other', fallback='').split()
|
||||
toplevel_langs = config.get(f'target.{target}', 'toplevel_langs', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
prefix = f'{os.getcwd()}/{prefix}%%'.replace('/.%%', '').replace('%%', '')
|
||||
build_dir = f'{prefix}/{build_dir}'
|
||||
out_dir = f'{prefix}/{out_dir}/{target}'
|
||||
|
||||
log(" - creating output directories")
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
log(" - copy needed files")
|
||||
for f in files_python_other:
|
||||
shutil.copy(f"{prefix}/{f}", f"{build_dir}/{os.path.basename(f)}")
|
||||
for f in files_other:
|
||||
d = os.path.dirname(f)
|
||||
os.makedirs(f"{build_dir}/{d}", exist_ok=True)
|
||||
shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}")
|
||||
|
||||
res = 0
|
||||
|
||||
i = 0
|
||||
for pfile in files_python:
|
||||
|
||||
log(" - copy", pfile)
|
||||
shutil.copy(f"{prefix}/{pfile}", build_dir)
|
||||
|
||||
log(" - writing Makefile for", pfile)
|
||||
with open(f'{build_dir}/Makefile', 'w') as f:
|
||||
f.write(f".SILENT:\nSIM ?= {simulator}\nTOPLEVEL_LANG ?= {toplevel_langs[i]}\nWAVES = 1\n")
|
||||
f.write(f"TOPLEVEL = {toplevels[i]}\nMODULE = {'.'.join(os.path.basename(pfile).split('.')[0:-1])}\n")
|
||||
for vfile in files_vhdl:
|
||||
f.write(f"VHDL_SOURCES += {prefix}/{vfile}\n")
|
||||
for vfile in files_verilog:
|
||||
f.write(f"VERILOG_SOURCES += {prefix}/{vfile}\n")
|
||||
|
||||
if simulator=='ghdl':
|
||||
f.write(f"SIM_ARGS += --vcd={os.path.basename(pfile)}.vcd\n")
|
||||
|
||||
f.write("include $(shell cocotb-config --makefiles)/Makefile.sim\n")
|
||||
|
||||
log(" - start cocotb")
|
||||
p = subprocess.Popen(f"make 2>&1 | tee {os.path.basename(pfile)}.log",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res |= p.returncode
|
||||
|
||||
shutil.copy(f"{build_dir}/{os.path.basename(pfile)}.log", out_dir)
|
||||
|
||||
if simulator=='ghdl':
|
||||
shutil.copy(f"{build_dir}/{os.path.basename(pfile)}.vcd", out_dir)
|
||||
elif simulator=='questa':
|
||||
os.system(f'wlf2vcd -o {out_dir}/{os.path.basename(pfile)}.vcd {build_dir}/vsim.wlf')
|
||||
|
||||
i += 1
|
||||
|
||||
return res
|
@ -6,7 +6,10 @@ import subprocess
|
||||
def execp(cmd, subprocesses, cwd):
|
||||
p = subprocess.Popen(cmd,
|
||||
shell=True, cwd=cwd,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdin=subprocess.DEVNULL,
|
||||
#stdout=subprocess.DEVNULL,
|
||||
#stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
@ -25,6 +28,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
ghdle_opts = config.get(f'target.{target}', 'ghdle_opts', fallback='')
|
||||
ghdlr_opts = config.get(f'target.{target}', 'ghdlr_opts', fallback='')
|
||||
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||
files_other = config.get(f'target.{target}', 'files_other', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
@ -36,6 +40,12 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
log(" - copy needed files")
|
||||
for f in files_other:
|
||||
d = os.path.dirname(f)
|
||||
os.makedirs(f"{build_dir}/{d}", exist_ok=True)
|
||||
shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}")
|
||||
|
||||
log(" - analyze files")
|
||||
res = 0
|
||||
for f in files_vhdl:
|
||||
@ -60,7 +70,8 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
extra = ''
|
||||
if runtime!='all':
|
||||
extra = f'--stop-time={runtime.replace(" ", "")}'
|
||||
res = execp(f"echo {toplevel} >> r.log && ghdl -r {ghdlr_opts} {extra} {toplevel} --vcd=out.vcd 2>&1 1>> r.log", subprocesses, build_dir)
|
||||
# res = execp(f"echo {toplevel} >> r.log && ghdl -r {ghdlr_opts} {toplevel} {extra} --vcd=out.vcd --wave=out.ghw 2>&1 | tee r.log", subprocesses, build_dir)
|
||||
res = execp(f"echo {toplevel} >> r.log && ./{toplevel} {ghdlr_opts} {extra} --vcd=out.vcd --wave=out.ghw 2>&1 | tee r.log", subprocesses, build_dir)
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/r.log', f'{out_dir}/r.log')
|
||||
# Ignore simulation errors: vhdl stopping with failure results in returned with 1
|
||||
@ -70,5 +81,6 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
|
||||
log(" - copy output files")
|
||||
shutil.copy(f'{build_dir}/out.vcd', f'{out_dir}/out.vcd')
|
||||
shutil.copy(f'{build_dir}/out.ghw', f'{out_dir}/out.ghw')
|
||||
|
||||
return 0
|
135
remotesyn/toolchains/gowin.py
Normal file
135
remotesyn/toolchains/gowin.py
Normal file
@ -0,0 +1,135 @@
|
||||
import shutil
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
import html2text
|
||||
|
||||
def do(config, target, log, subprocesses, prefix='.'):
|
||||
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
|
||||
shutil.rmtree(config.get('project', 'out_dir', fallback='out'), True)
|
||||
|
||||
log(" - parsing options")
|
||||
family = config.get(f'target.{target}', 'family', fallback='')
|
||||
device = config.get(f'target.{target}', 'device', fallback='')
|
||||
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
|
||||
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
|
||||
files_con= config.get(f'target.{target}', 'files_con', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
prefix = f'{os.getcwd()}/{prefix}'
|
||||
build_dir = f'{prefix}/{build_dir}'
|
||||
out_dir = f'{prefix}/{out_dir}/{target}'
|
||||
|
||||
log(" - creating output directories")
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
log(" - writing scripts")
|
||||
with open(f'{build_dir}/synth.tcl', 'w') as f:
|
||||
f.write(f'set_device {device} -name {family}\n')
|
||||
|
||||
for s in files_vhdl:
|
||||
if s=='':
|
||||
continue
|
||||
f.write(f'add_file {prefix}/{s}\n')
|
||||
for s in files_verilog:
|
||||
if s=='':
|
||||
continue
|
||||
f.write(f'add_file {prefix}/{s}\n')
|
||||
for s in files_con:
|
||||
if s=='':
|
||||
continue
|
||||
f.write(f'add_file {prefix}/{s}\n')
|
||||
|
||||
f.write('set_option -synthesis_tool gowinsynthesis\n')
|
||||
f.write(f'set_option -output_base_name {toplevel}\n')
|
||||
f.write(f'set_option -top_module {toplevel}\n')
|
||||
f.write('run syn\n')
|
||||
|
||||
with open(f'{build_dir}/pnr.tcl', 'w') as f:
|
||||
f.write(f'set_device {device} -name {family}\n')
|
||||
f.write('set_option -synthesis_tool gowinsynthesis\n')
|
||||
f.write(f'set_option -output_base_name {toplevel}\n')
|
||||
f.write(f'set_option -top_module {toplevel}\n')
|
||||
for s in files_con:
|
||||
if s=='':
|
||||
continue
|
||||
f.write(f'add_file {prefix}/{s}\n')
|
||||
f.write(f'add_file {build_dir}/impl/gwsynthesis/{toplevel}.vg\n')
|
||||
|
||||
f.write('run pnr\n')
|
||||
|
||||
log(' - run syntesis')
|
||||
p = subprocess.Popen(f"gw_sh synth.tcl",
|
||||
shell = True,
|
||||
cwd = build_dir,
|
||||
stdin = subprocess.DEVNULL,
|
||||
# stdout = subprocess.DEVNULL,
|
||||
# stderr = subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res = p.returncode
|
||||
|
||||
shutil.copy(f'{build_dir}/impl/gwsynthesis/{toplevel}.log', f'{out_dir}/synth.log')
|
||||
if res!=0:
|
||||
log("ERROR: synthesis failed with:", res)
|
||||
return res
|
||||
shutil.copy(f'{build_dir}/impl/gwsynthesis/{toplevel}.vg', f'{out_dir}/synth_netlist.vg')
|
||||
with open(f'{build_dir}/impl/gwsynthesis/{toplevel}_syn.rpt.html', 'r') as fin, open(f'{out_dir}/synth_rpt.md', 'w') as fout:
|
||||
text_maker = html2text.HTML2Text()
|
||||
text_maker.bypass_tables = False
|
||||
text_maker.ignore_links = True
|
||||
text_maker.body_width = 500
|
||||
fout.write(text_maker.handle(fin.read()))
|
||||
|
||||
log(' - run PnR')
|
||||
p = subprocess.Popen(f"gw_sh pnr.tcl",
|
||||
shell = True,
|
||||
cwd = build_dir,
|
||||
stdin = subprocess.DEVNULL,
|
||||
# stdout = subprocess.DEVNULL,
|
||||
# stderr = subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res = p.returncode
|
||||
|
||||
shutil.copy(f'{build_dir}/impl/pnr/{toplevel}.log', f'{out_dir}/pnr.log')
|
||||
if res!=0:
|
||||
log("ERROR: pnr failed with:", res)
|
||||
return res
|
||||
shutil.copy(f'{build_dir}/impl/pnr/{toplevel}.fs', f'{out_dir}/{toplevel}.fs')
|
||||
shutil.copy(f'{build_dir}/impl/pnr/{toplevel}.bin', f'{out_dir}/{toplevel}.bin')
|
||||
with open(f'{build_dir}/impl/pnr/{toplevel}.rpt.html', 'r') as fin, open(f'{out_dir}/rpt.md', 'w') as fout:
|
||||
text_maker = html2text.HTML2Text()
|
||||
text_maker.bypass_tables = False
|
||||
text_maker.ignore_links = True
|
||||
text_maker.body_width = 500
|
||||
fout.write(text_maker.handle(fin.read()))
|
||||
with open(f'{build_dir}/impl/pnr/{toplevel}.power.html', 'r') as fin, open(f'{out_dir}/power.md', 'w') as fout:
|
||||
text_maker = html2text.HTML2Text()
|
||||
text_maker.bypass_tables = False
|
||||
text_maker.ignore_links = True
|
||||
text_maker.body_width = 500
|
||||
fout.write(text_maker.handle(fin.read()))
|
||||
with open(f'{build_dir}/impl/pnr/{toplevel}.pin.html', 'r') as fin, open(f'{out_dir}/pin.md', 'w') as fout:
|
||||
text_maker = html2text.HTML2Text()
|
||||
text_maker.bypass_tables = False
|
||||
text_maker.ignore_links = True
|
||||
text_maker.body_width = 500
|
||||
fout.write(text_maker.handle(fin.read()))
|
||||
with open(f'{build_dir}/impl/pnr/{toplevel}_tr_content.html', 'r') as fin, open(f'{out_dir}/timing.md', 'w') as fout:
|
||||
text_maker = html2text.HTML2Text()
|
||||
text_maker.bypass_tables = False
|
||||
text_maker.ignore_links = True
|
||||
text_maker.body_width = 500
|
||||
fout.write(text_maker.handle(fin.read()))
|
||||
|
||||
return res
|
@ -10,12 +10,13 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
|
||||
log(" - parsing options")
|
||||
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
|
||||
vcdlevels = config.get(f'target.{target}', 'vcdlevels', fallback='1')
|
||||
vcdlevels = config.get(f'target.{target}', 'vcdlevels', fallback='10')
|
||||
runtime = config.get(f'target.{target}', 'runtime', fallback='100 ns')
|
||||
fuse_opts = config.get(f'target.{target}', 'fuse_opts', fallback='')
|
||||
isim_opts = config.get(f'target.{target}', 'isim_opts', fallback='')
|
||||
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
|
||||
files_other = config.get(f'target.{target}', 'files_other', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
@ -30,6 +31,12 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
log(" - copy needed files")
|
||||
for f in files_other:
|
||||
d = os.path.dirname(f)
|
||||
os.makedirs(f"{build_dir}/{d}", exist_ok=True)
|
||||
shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}")
|
||||
|
||||
log(" - writing project file")
|
||||
with open(f'{build_dir}/sim.prj', 'w') as f:
|
||||
for s in files_vhdl:
|
||||
@ -51,7 +58,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
res = p.returncode
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/ffuse.log', f'{out_dir}/fuse.log')
|
||||
shutil.copy(f'{build_dir}/fuse.log', f'{out_dir}/fuse.log')
|
||||
|
||||
if res!=0:
|
||||
log("ERROR: fuse returned with:", res)
|
||||
@ -61,15 +68,18 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
with open(f'{build_dir}/sim.tcl', 'w') as f:
|
||||
f.write("onerror {resume}\n")
|
||||
f.write("vcd dumpfile sim.vcd\n")
|
||||
f.write(f"vcd dumpvars -m {toplevel} -l {vcdlevels}\n")
|
||||
f.write(f"vcd dumpvars -m {toplevel.split()[0]} -l {vcdlevels}\n")
|
||||
f.write("vcd dumpon\n")
|
||||
f.write(f"run {runtime}\n")
|
||||
f.write("vcd dumpflush\nquit\n")
|
||||
|
||||
log(" - run sim")
|
||||
p = subprocess.Popen(f"./sim {isim_opts} -tclbatch sim.tcl > sim.log",
|
||||
p = subprocess.Popen(f"./sim {isim_opts} -tclbatch sim.tcl | tee sim.log",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
|
52
remotesyn/toolchains/make.py
Normal file
52
remotesyn/toolchains/make.py
Normal file
@ -0,0 +1,52 @@
|
||||
import shutil
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
def do(config, target, log, subprocesses, prefix='.'):
|
||||
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
|
||||
|
||||
log("Starting make build process")
|
||||
|
||||
log(" - parsing options")
|
||||
files_makefile = config.get(f'target.{target}', 'files_makefile', fallback='')
|
||||
buildroot = config.get(f'target.{target}', 'buildroot', fallback='.')
|
||||
output_files = config.get(f'target.{target}', 'output_files', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
prefix = f'{os.getcwd()}/{prefix}'
|
||||
build_dir = f'{prefix}/{build_dir}'
|
||||
out_dir = f'{prefix}/{out_dir}/{target}'
|
||||
|
||||
log(" - creating output directories")
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
log(" - Copy makefile to build directory")
|
||||
shutil.copy(f"{prefix}/{files_makefile}", f"{build_dir}/Makefile")
|
||||
|
||||
log(" - run make")
|
||||
p = subprocess.Popen(f"BUILDROOT={prefix}/{buildroot} make 2>make.log",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res = p.returncode
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/make.log', f'{out_dir}/make.log')
|
||||
|
||||
if res!=0:
|
||||
log("ERROR: make returned with:", res)
|
||||
return res
|
||||
|
||||
log(" - copy output files")
|
||||
for f in output_files:
|
||||
shutil.copy(f'{build_dir}/{f}', f'{out_dir}/{os.path.basename(f)}')
|
||||
|
||||
return 0
|
41
remotesyn/toolchains/qemu.py
Normal file
41
remotesyn/toolchains/qemu.py
Normal file
@ -0,0 +1,41 @@
|
||||
import shutil
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
def do(config, target, log, subprocesses, prefix='.'):
|
||||
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
|
||||
|
||||
log("Starting QEMU simulation")
|
||||
|
||||
log(" - parsing options")
|
||||
files_executable = config.get(f'target.{target}', 'files_executable', fallback='')
|
||||
arch = config.get(f'target.{target}', 'arch', fallback='arm')
|
||||
machine = config.get(f'target.{target}', 'machine', fallback='xilinx-zynq-a9')
|
||||
ram = config.get(f'target.{target}', 'ram', fallback='500M')
|
||||
extra_opts = config.get(f'target.{target}', 'extra_opts', fallback='')
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
prefix = f'{os.getcwd()}/{prefix}'
|
||||
build_dir = f'{prefix}/{build_dir}'
|
||||
out_dir = f'{prefix}/{out_dir}/{target}'
|
||||
|
||||
log(" - creating output directories")
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
log(" - run QEMU, quit r(m)build to stop")
|
||||
p = subprocess.Popen(f"qemu-system-{arch} -machine {machine} -kernel {prefix}/{files_executable} {extra_opts} -m {ram} -nographic 2>error.log | tee run.log",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res = p.returncode
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/run.log', f'{out_dir}/run.log')
|
||||
shutil.copy(f'{build_dir}/error.log', f'{out_dir}/error.log')
|
||||
|
||||
return 0
|
87
remotesyn/toolchains/questa.py
Normal file
87
remotesyn/toolchains/questa.py
Normal file
@ -0,0 +1,87 @@
|
||||
from importlib.metadata import files
|
||||
import shutil
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
def do(config, target, log, subprocesses, prefix='.'):
|
||||
# shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
|
||||
|
||||
log("Starting simulation")
|
||||
|
||||
log(" - parsing options")
|
||||
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
|
||||
runtime = config.get(f'target.{target}', 'runtime', fallback='100 ns')
|
||||
vsim_opts = config.get(f'target.{target}', 'vsim_opts', fallback='')
|
||||
vcom_opts = config.get(f'target.{target}', 'vcom_opts', fallback='')
|
||||
vlog_opts = config.get(f'target.{target}', 'vlog_opts', fallback='')
|
||||
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
|
||||
files_sysverilog = config.get(f'target.{target}', 'files_sysverilog', fallback='').split()
|
||||
files_c = config.get(f'target.{target}', 'files_c', fallback='').split()
|
||||
files_other = config.get(f'target.{target}', 'files_other', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
prefix = f'{os.getcwd()}/{prefix}'
|
||||
build_dir = f'{prefix}/{build_dir}'
|
||||
out_dir = f'{prefix}/{out_dir}/{target}'
|
||||
|
||||
log(" - creating output directories")
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
log(" - copy needed files")
|
||||
for f in files_other:
|
||||
d = os.path.dirname(f)
|
||||
os.makedirs(f"{build_dir}/{d}", exist_ok=True)
|
||||
shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}")
|
||||
|
||||
files_c_wp = {f'{prefix}/{f}' for f in files_c}
|
||||
|
||||
log(" - writing compile file")
|
||||
with open(f'{build_dir}/do.sh', 'w') as f:
|
||||
f.write(f'vlib work\nvmap work work\n')
|
||||
for s in files_verilog:
|
||||
f.write(f"vlog {vlog_opts} {prefix}/{s}\n")
|
||||
for s in files_vhdl:
|
||||
f.write(f"vcom {vcom_opts} {prefix}/{s}\n")
|
||||
for s in files_sysverilog:
|
||||
f.write(f"vlog -sv {vlog_opts} {prefix}/{s}\n")
|
||||
f.write(f"gcc -g -fPIC -shared -Bsymbolic -o import.so {' '.join(files_c_wp)}\n")
|
||||
extra = vsim_opts
|
||||
if len(files_c_wp)>0:
|
||||
extra = ' -sv_lib import'
|
||||
f.write(f"vsim -c -do do.do {extra} -vcd=+multid+vhvar -vcddump=out.vcd {toplevel}")
|
||||
|
||||
log(" - writing do file")
|
||||
rtime = "-all"
|
||||
if runtime != "all":
|
||||
rtime = runtime
|
||||
with open(f'{build_dir}/do.do', 'w') as f:
|
||||
# f.write(f"vcd file out.vcd\n vcd add -r -in -out -inout -internal -ports *\nrun {rtime}\nquit\n");
|
||||
f.write(f"\nrun {rtime}\nquit\n");
|
||||
|
||||
log(" - run vsim")
|
||||
p = subprocess.Popen(f"bash ./do.sh 2>&1 | tee do.log",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL,
|
||||
#stdout=subprocess.DEVNULL,
|
||||
#stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res = p.returncode
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/do.log', f'{out_dir}/do.log')
|
||||
|
||||
if res!=0:
|
||||
log("ERROR: vsim returned with", res)
|
||||
return res
|
||||
|
||||
log(" - copy output files")
|
||||
shutil.copy(f'{build_dir}/out.vcd', f'{out_dir}/out.vcd')
|
||||
|
||||
return 0
|
@ -6,7 +6,9 @@ import subprocess
|
||||
def execp(cmd, subprocesses, cwd):
|
||||
p = subprocess.Popen(cmd,
|
||||
shell=True, cwd=cwd,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
@ -55,7 +57,10 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
for d in os.listdir(f'{build_dir}'):
|
||||
if os.path.isdir(f'{build_dir}/{d}') and d.startswith(oname):
|
||||
shutil.copy(f'{build_dir}/{d}/logfile.txt', f'{out_dir}/{d}.log')
|
||||
try:
|
||||
shutil.copytree(f'{build_dir}/{d}/engine_0', f'{out_dir}/{d}', dirs_exist_ok=True)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
if res!=0:
|
||||
log(" - [-]")
|
||||
|
@ -20,7 +20,10 @@ def bitgen(config, target, log, subprocesses, prefix='.') -> int:
|
||||
log(" - run bitgen")
|
||||
p = subprocess.Popen(f"bitgen -intstyle xflow {bitgen_opts} -g Binary:Yes -w {out_dir}/{target}.ncd {target}.bit {out_dir}/{target}.pcf 2> bitgen.log",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
|
@ -10,7 +10,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int:
|
||||
package = config.get(f'target.{target}', 'package', fallback='')
|
||||
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
|
||||
coregen_opts = config.get(f'target.{target}', 'coregen_opts', fallback='')
|
||||
files_xco = config.get(f'target.{target}', 'files_xco', fallback='').split()
|
||||
files_def = config.get(f'target.{target}', 'files_def', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
|
||||
@ -24,7 +24,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int:
|
||||
|
||||
res = 0
|
||||
|
||||
for fxco in files_xco:
|
||||
for fxco in files_def:
|
||||
cname = fxco.split('/')[-1].split('.')[0]
|
||||
|
||||
log(" - Generating", cname, "...")
|
||||
@ -40,6 +40,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int:
|
||||
f.write(f'SET flowvendor = Other\n')
|
||||
f.write(f'SET verilogsim = true\n')
|
||||
f.write(f'SET vhdlsim = true\n')
|
||||
f.write(f'SET implementationfiletype = ngc\n')
|
||||
|
||||
log(" - run coregen")
|
||||
p = subprocess.Popen(f"coregen {coregen_opts} -p coregen_{cname}.cgp -b {prefix}/{fxco}",
|
||||
@ -55,9 +56,22 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int:
|
||||
|
||||
if res==0:
|
||||
log(" - copy output files")
|
||||
try:
|
||||
shutil.copy(f'{build_dir}/{cname}.vhd', f'{out_dir}/{cname}.vhd')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
shutil.copy(f'{build_dir}/{cname}.v', f'{out_dir}/{cname}.v')
|
||||
# shutil.copy(f'{build_dir}/{cname}.ngc', f'{out_dir}/{cname}.ngc')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
shutil.copy(f'{build_dir}/{cname}.ngc', f'{out_dir}/{cname}.ngc')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
shutil.copy(f'{build_dir}/{cname}.xco', f'{out_dir}/{cname}.xco')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
else:
|
||||
return res
|
||||
|
||||
|
@ -24,7 +24,10 @@ def map(config, target, log, subprocesses, prefix='.') -> int:
|
||||
log(" - run map")
|
||||
p = subprocess.Popen(f"map -intstyle xflow -p {devstring} -detail {map_opts} -ol high -xe n -w {out_dir}/{target}.ngd -o impl.map.ncd impl.pcf",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
|
@ -25,7 +25,10 @@ def ngdbuild(config, target, log, subprocesses, prefix='.') -> int:
|
||||
log(" - run ngdbuild")
|
||||
p = subprocess.Popen(f"ngdbuild -intstyle xflow -p {devstring} -uc {prefix}/{files_con[0]} {ngdbuild_opts} {out_dir}/{target}.ngc impl.ngd",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
|
@ -28,5 +28,6 @@ def trce(config, target, log, subprocesses, prefix='.') -> int:
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/{target}.twr', f'{out_dir}/timing.log')
|
||||
shutil.copy(f'{build_dir}/{target}.twx', f'{out_dir}/timing.twx')
|
||||
|
||||
return res
|
@ -10,6 +10,8 @@ def xst(config, target, log, subprocesses, prefix='.') -> int:
|
||||
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
|
||||
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
|
||||
xst_opts = config.get(f'target.{target}', 'xst_opts', fallback='')
|
||||
netgensynth_opts = config.get(f'target.{target}', 'netgensynth_opts', fallback='-ofmt verilog')
|
||||
netgensynth_type = config.get(f'target.{target}', 'netgensynth_type', fallback='-sim')
|
||||
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
@ -39,22 +41,52 @@ def xst(config, target, log, subprocesses, prefix='.') -> int:
|
||||
with open(f'{build_dir}/prj.scr', 'w') as f:
|
||||
f.write(f'run\n-ifn syn.prj\n-ofn syn.ngc\n-ifmt mixed\n')
|
||||
f.write(f'-top {toplevel}\n')
|
||||
f.write(f'-p {devstring}\n-glob_opt max_delay -opt_mode speed')
|
||||
f.write(f'-p {devstring}\n-glob_opt max_delay -opt_mode speed\n')
|
||||
f.write(f'-read_cores YES')
|
||||
|
||||
log(" - run xst")
|
||||
p = subprocess.Popen(f"xst -intstyle xflow {xst_opts} -ifn prj.scr",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res = p.returncode
|
||||
|
||||
if res==0:
|
||||
log(" - copy output files")
|
||||
shutil.copy(f'{build_dir}/syn.ngc', f'{out_dir}/{target}.ngc')
|
||||
|
||||
log(" - run netgen")
|
||||
extra = ""
|
||||
if netgensynth_type=="-sim" and not netgensynth_opts.__contains__("-ofmt vhdl"):
|
||||
extra = "-insert_glbl true -ism"
|
||||
p = subprocess.Popen(f"netgen -intstyle xflow {netgensynth_type} -w {extra} {netgensynth_opts} {out_dir}/{target}.ngc 2>&1 >> prj.srp",
|
||||
shell=True, cwd=build_dir,
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
# stderr=subprocess.DEVNULL
|
||||
)
|
||||
subprocesses.append(p)
|
||||
while p.poll() is None:
|
||||
time.sleep(1)
|
||||
res |= p.returncode
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/prj.srp', f'{out_dir}/xst.log')
|
||||
|
||||
if res==0:
|
||||
log(" - copy output files")
|
||||
shutil.copy(f'{build_dir}/syn.ngc', f'{out_dir}/{target}.ngc')
|
||||
try:
|
||||
shutil.copy(f'{build_dir}/{target}.v', f'{out_dir}/{target}-synth.v')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
shutil.copy(f'{build_dir}/{target}.vhd', f'{out_dir}/{target}-synth.vhd')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
return res
|
@ -16,6 +16,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
|
||||
files_sysverilog = config.get(f'target.{target}', 'files_sysverilog', fallback='').split()
|
||||
files_xci = config.get(f'target.{target}', 'files_xci', fallback='').split()
|
||||
files_c = config.get(f'target.{target}', 'files_c', fallback='').split()
|
||||
files_other = config.get(f'target.{target}', 'files_other', fallback='').split()
|
||||
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||
@ -48,7 +49,9 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
for s in files_other:
|
||||
f.write(f"add_files -norecurse -scan_for_includes \"{prefix}/{s}\"\n")
|
||||
f.write(f"import_files -norecurse \"{prefix}/{s}\"\n")
|
||||
# TODO C files for VPI
|
||||
for s in files_c:
|
||||
f.write(f"add_files -norecurse -scan_for_includes \"{prefix}/{s}\"\n")
|
||||
f.write(f"import_files -norecurse \"{prefix}/{s}\"\n")
|
||||
|
||||
f.write(f"set_property top {toplevel} [get_filesets sim_1]\n")
|
||||
f.write("set_property top_lib xil_defaultlib [get_filesets sim_1]\n")
|
||||
@ -106,7 +109,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
|
||||
log(" - compile")
|
||||
|
||||
p = subprocess.Popen(f'bash compile.sh',
|
||||
p = subprocess.Popen(f'bash compile.sh 2>&1 | tee comp.log',
|
||||
shell=True, cwd=f'{build_dir}/sim/sim.sim/sim_1/behav/xsim',
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocesses.append(p)
|
||||
@ -115,7 +118,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
res = p.returncode
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/sim/sim.sim/sim_1/behav/xsim/compile.log', f'{out_dir}/compile.log')
|
||||
shutil.copy(f'{build_dir}/sim/sim.sim/sim_1/behav/xsim/comp.log', f'{out_dir}/compile.log')
|
||||
|
||||
if res!=0:
|
||||
log("ERROR: compile returned with", res)
|
||||
@ -123,7 +126,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
|
||||
log(" - elaborate")
|
||||
|
||||
p = subprocess.Popen(f'bash elaborate.sh',
|
||||
p = subprocess.Popen(f'bash elaborate.sh 2>&1 | tee elab.log',
|
||||
shell=True, cwd=f'{build_dir}/sim/sim.sim/sim_1/behav/xsim',
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocesses.append(p)
|
||||
@ -132,7 +135,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
res = p.returncode
|
||||
|
||||
log(" - copy logs")
|
||||
shutil.copy(f'{build_dir}/sim/sim.sim/sim_1/behav/xsim/elaborate.log', f'{out_dir}/elaborate.log')
|
||||
shutil.copy(f'{build_dir}/sim/sim.sim/sim_1/behav/xsim/elab.log', f'{out_dir}/elaborate.log')
|
||||
|
||||
if res!=0:
|
||||
log("ERROR: elaborate returned with", res)
|
||||
@ -144,7 +147,7 @@ def do(config, target, log, subprocesses, prefix='.'):
|
||||
|
||||
log(" - simulate")
|
||||
|
||||
p = subprocess.Popen(f'bash simulate.sh',
|
||||
p = subprocess.Popen(f'bash simulate.sh 2>&1 | tee simulate.log',
|
||||
shell=True, cwd=f'{build_dir}/sim/sim.sim/sim_1/behav/xsim',
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocesses.append(p)
|
||||
|
@ -1,12 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import configparser
|
||||
from re import sub
|
||||
import sys
|
||||
import signal
|
||||
|
||||
def log(*args):
|
||||
print(*args)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def print_help():
|
||||
log("Unified FPGA synthesizer frontend\r\n(c) Joppe Blondel - 2022\r\n")
|
||||
log(f"Usage: {sys.argv[0]} [ OPTIONS ] target ...")
|
||||
@ -45,7 +48,20 @@ if __name__=="__main__":
|
||||
|
||||
subprocesses = []
|
||||
|
||||
try:
|
||||
def sighandler(num, frame):
|
||||
if num==signal.SIGINT:
|
||||
log("\rStopping rbuild")
|
||||
for p in subprocesses:
|
||||
p.terminate()
|
||||
signal.alarm(4)
|
||||
elif num==signal.SIGALRM:
|
||||
log("Force killing subprocesses")
|
||||
for p in subprocesses:
|
||||
p.kill()
|
||||
exit(0)
|
||||
|
||||
signal.signal(signal.SIGINT, sighandler)
|
||||
signal.signal(signal.SIGALRM, sighandler)
|
||||
|
||||
for target in targets:
|
||||
|
||||
@ -67,9 +83,3 @@ if __name__=="__main__":
|
||||
if ret!=0:
|
||||
log("ERROR: toolchain returned with", ret)
|
||||
exit(ret)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
log("\rStopping rbuild")
|
||||
for p in subprocesses:
|
||||
p.kill()
|
||||
exit(0)
|
@ -7,6 +7,7 @@ import base64
|
||||
import struct
|
||||
import os
|
||||
import json
|
||||
import signal
|
||||
|
||||
def cmd(cmd, channel):
|
||||
channel.exec_command(base64.encodebytes(cmd))
|
||||
@ -68,9 +69,10 @@ def recv_dir(channel, dr):
|
||||
print("<<<", dr)
|
||||
cmd(b'ls'+sstr(dr), channel)
|
||||
while True:
|
||||
status = channel.recv(2)
|
||||
if status != b'\x00\x00':
|
||||
status = channel.recv(1)
|
||||
if status != b'\x00':
|
||||
break
|
||||
status += channel.recv(1)
|
||||
if status!=b'OK':
|
||||
msg = channel.recv(1024)
|
||||
print("Error:", bytes.decode(msg, 'ascii'))
|
||||
@ -145,16 +147,31 @@ if __name__=="__main__":
|
||||
exit(1)
|
||||
|
||||
subprocesses = []
|
||||
stopped = False
|
||||
|
||||
def sighandler(num, frame):
|
||||
global stopped
|
||||
if num==signal.SIGINT:
|
||||
print("\rStopping rbuild")
|
||||
stopped = True
|
||||
for p in subprocesses:
|
||||
p.terminate()
|
||||
exit(0)
|
||||
|
||||
signal.signal(signal.SIGINT, sighandler)
|
||||
signal.signal(signal.SIGALRM, sighandler)
|
||||
|
||||
try:
|
||||
for target in targets:
|
||||
if stopped:
|
||||
break
|
||||
|
||||
# Send project identification
|
||||
cmd(b'id' + struct.pack('>q', hash(host_key.get_base64())), channel)
|
||||
# Send config
|
||||
cmd(b'cf' + sstr(json.dumps({s:dict(config.items(s)) for s in config.sections()})), channel)
|
||||
|
||||
for target in targets:
|
||||
|
||||
print("Target", target)
|
||||
print("LOCAL: Target", target)
|
||||
|
||||
toolchain = config.get(f'target.{target}', 'toolchain', fallback='NONE')
|
||||
if toolchain=='NONE':
|
||||
@ -174,7 +191,11 @@ if __name__=="__main__":
|
||||
send_file(channel, f)
|
||||
|
||||
cmd(b'do'+sstr(target), channel)
|
||||
status = channel.recv(2)
|
||||
while True:
|
||||
status = channel.recv(1)
|
||||
if status!='b\x00':
|
||||
break
|
||||
status += channel.recv(1)
|
||||
end = -1
|
||||
while end<0:
|
||||
data = channel.recv(8)
|
||||
@ -184,7 +205,7 @@ if __name__=="__main__":
|
||||
print(str(data, 'utf-8'), end='', flush=True)
|
||||
sys.stdout.flush()
|
||||
|
||||
ret = 0
|
||||
ret = int.from_bytes(channel.recv(4), 'big')
|
||||
|
||||
# Receive output dir
|
||||
recv_dir(channel, config.get('project', 'out_dir', fallback='out'))
|
||||
@ -193,14 +214,10 @@ if __name__=="__main__":
|
||||
print("ERROR: toolchain returned with", ret)
|
||||
exit(ret)
|
||||
|
||||
cmd(b'ex', channel)
|
||||
|
||||
except paramiko.ssh_exception.SSHException as e:
|
||||
print("ERROR: Connection error...", e)
|
||||
for p in subprocesses:
|
||||
p.kill()
|
||||
exit(0)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\rStopping rmbuild")
|
||||
for p in subprocesses:
|
||||
p.kill()
|
||||
exit(0)
|
@ -100,7 +100,6 @@ class SSHServer(paramiko.ServerInterface):
|
||||
for t in self.threads:
|
||||
if type(t) is not NoneType:
|
||||
t.stop()
|
||||
t.join()
|
||||
|
||||
def check_channel_request(self, kind, chanid):
|
||||
if kind == 'session':
|
||||
@ -143,7 +142,7 @@ class SSHServer(paramiko.ServerInterface):
|
||||
# Exit
|
||||
elif cmd==b'ex':
|
||||
print('<', self.identifier)
|
||||
self.event.set()
|
||||
self.stop()
|
||||
|
||||
# Config
|
||||
elif cmd==b'cf':
|
||||
@ -245,9 +244,10 @@ class Connection(threading.Thread):
|
||||
time.sleep(0.2)
|
||||
else:
|
||||
print("Connection", self.addr, "closed")
|
||||
if server.identifier!='':
|
||||
pass
|
||||
|
||||
print("Deleting directory")
|
||||
shutil.rmtree(server.identifier, True)
|
||||
|
||||
transport.close()
|
||||
|
||||
def print_help():
|
||||
|
Reference in New Issue
Block a user