forked from M-Labs/artiq-zynq
moved related libraries, culled unnecessary ones
This commit is contained in:
parent
7e97e86446
commit
731f52992f
38
src/libboard_artiqzynq/clock.rs
Normal file
38
src/libboard_artiqzynq/clock.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use core::i64;
|
||||
use csr; // <- port
|
||||
|
||||
const INIT: u64 = i64::MAX as u64;
|
||||
const FREQ: u64 = csr::CONFIG_CLOCK_FREQUENCY as u64;
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
csr::timer0::en_write(0);
|
||||
csr::timer0::load_write(INIT);
|
||||
csr::timer0::reload_write(INIT);
|
||||
csr::timer0::en_write(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_us() -> u64 {
|
||||
unsafe {
|
||||
csr::timer0::update_value_write(1);
|
||||
(INIT - csr::timer0::value_read()) / (FREQ / 1_000_000)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ms() -> u64 {
|
||||
unsafe {
|
||||
csr::timer0::update_value_write(1);
|
||||
(INIT - csr::timer0::value_read()) / (FREQ / 1_000)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spin_us(interval: u64) {
|
||||
unsafe {
|
||||
csr::timer0::update_value_write(1);
|
||||
let threshold = csr::timer0::value_read() - interval * (FREQ / 1_000_000);
|
||||
while csr::timer0::value_read() > threshold {
|
||||
csr::timer0::update_value_write(1)
|
||||
}
|
||||
}
|
||||
}
|
107
src/libboard_artiqzynq/drtio_routing.rs
Normal file
107
src/libboard_artiqzynq/drtio_routing.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use board_misoc::config; // <- port
|
||||
#[cfg(has_drtio_routing)]
|
||||
use board_misoc::csr; // <- port
|
||||
use core::fmt;
|
||||
|
||||
#[cfg(has_drtio_routing)]
|
||||
pub const DEST_COUNT: usize = 256;
|
||||
#[cfg(not(has_drtio_routing))]
|
||||
pub const DEST_COUNT: usize = 0;
|
||||
pub const MAX_HOPS: usize = 32;
|
||||
pub const INVALID_HOP: u8 = 0xff;
|
||||
|
||||
pub struct RoutingTable(pub [[u8; MAX_HOPS]; DEST_COUNT]);
|
||||
|
||||
impl RoutingTable {
|
||||
// default routing table is for star topology with no repeaters
|
||||
pub fn default_master(default_n_links: usize) -> RoutingTable {
|
||||
let mut ret = RoutingTable([[INVALID_HOP; MAX_HOPS]; DEST_COUNT]);
|
||||
let n_entries = default_n_links + 1; // include local RTIO
|
||||
for i in 0..n_entries {
|
||||
ret.0[i][0] = i as u8;
|
||||
}
|
||||
for i in 1..n_entries {
|
||||
ret.0[i][1] = 0x00;
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
// use this by default on satellite, as they receive
|
||||
// the routing table from the master
|
||||
pub fn default_empty() -> RoutingTable {
|
||||
RoutingTable([[INVALID_HOP; MAX_HOPS]; DEST_COUNT])
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RoutingTable {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "RoutingTable {{")?;
|
||||
for i in 0..DEST_COUNT {
|
||||
if self.0[i][0] != INVALID_HOP {
|
||||
write!(f, " {}:", i)?;
|
||||
for j in 0..MAX_HOPS {
|
||||
if self.0[i][j] == INVALID_HOP {
|
||||
break;
|
||||
}
|
||||
write!(f, " {}", self.0[i][j])?;
|
||||
}
|
||||
write!(f, ";")?;
|
||||
}
|
||||
}
|
||||
write!(f, " }}")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn config_routing_table(default_n_links: usize) -> RoutingTable {
|
||||
let mut ret = RoutingTable::default_master(default_n_links);
|
||||
let ok = config::read("routing_table", |result| {
|
||||
if let Ok(data) = result {
|
||||
if data.len() == DEST_COUNT*MAX_HOPS {
|
||||
for i in 0..DEST_COUNT {
|
||||
for j in 0..MAX_HOPS {
|
||||
ret.0[i][j] = data[i*MAX_HOPS+j];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
if !ok {
|
||||
warn!("could not read routing table from configuration, using default");
|
||||
}
|
||||
info!("routing table: {}", ret);
|
||||
ret
|
||||
}
|
||||
|
||||
#[cfg(has_drtio_routing)]
|
||||
pub fn interconnect_enable(routing_table: &RoutingTable, rank: u8, destination: u8) {
|
||||
let hop = routing_table.0[destination as usize][rank as usize];
|
||||
unsafe {
|
||||
csr::routing_table::destination_write(destination);
|
||||
csr::routing_table::hop_write(hop);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(has_drtio_routing)]
|
||||
pub fn interconnect_disable(destination: u8) {
|
||||
unsafe {
|
||||
csr::routing_table::destination_write(destination);
|
||||
csr::routing_table::hop_write(INVALID_HOP);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(has_drtio_routing)]
|
||||
pub fn interconnect_enable_all(routing_table: &RoutingTable, rank: u8) {
|
||||
for i in 0..DEST_COUNT {
|
||||
interconnect_enable(routing_table, rank, i as u8);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(has_drtio_routing)]
|
||||
pub fn interconnect_disable_all() {
|
||||
for i in 0..DEST_COUNT {
|
||||
interconnect_disable(i as u8);
|
||||
}
|
||||
}
|
153
src/libboard_artiqzynq/drtioaux.rs
Normal file
153
src/libboard_artiqzynq/drtioaux.rs
Normal file
@ -0,0 +1,153 @@
|
||||
use core::slice;
|
||||
use crc;
|
||||
|
||||
use io::{ProtoRead, ProtoWrite, Cursor, Error as IoError};
|
||||
use board_misoc::{csr::DRTIOAUX, mem::DRTIOAUX_MEM}; // <- port
|
||||
use clock;
|
||||
use proto_artiq::drtioaux_proto::Error as ProtocolError;
|
||||
|
||||
pub use proto_artiq::drtioaux_proto::Packet;
|
||||
|
||||
// this is parametric over T because there's no impl Fail for !.
|
||||
#[derive(Fail, Debug)]
|
||||
pub enum Error<T> {
|
||||
#[fail(display = "gateware reported error")]
|
||||
GatewareError,
|
||||
#[fail(display = "packet CRC failed")]
|
||||
CorruptedPacket,
|
||||
|
||||
#[fail(display = "link is down")]
|
||||
LinkDown,
|
||||
#[fail(display = "timed out waiting for data")]
|
||||
TimedOut,
|
||||
#[fail(display = "unexpected reply")]
|
||||
UnexpectedReply,
|
||||
|
||||
#[fail(display = "routing error")]
|
||||
RoutingError,
|
||||
|
||||
#[fail(display = "protocol error: {}", _0)]
|
||||
Protocol(#[cause] ProtocolError<T>)
|
||||
}
|
||||
|
||||
impl<T> From<ProtocolError<T>> for Error<T> {
|
||||
fn from(value: ProtocolError<T>) -> Error<T> {
|
||||
Error::Protocol(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<IoError<T>> for Error<T> {
|
||||
fn from(value: IoError<T>) -> Error<T> {
|
||||
Error::Protocol(ProtocolError::Io(value))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(linkno: u8) {
|
||||
let linkno = linkno as usize;
|
||||
unsafe {
|
||||
// clear buffer first to limit race window with buffer overflow
|
||||
// error. We assume the CPU is fast enough so that no two packets
|
||||
// will be received between the buffer and the error flag are cleared.
|
||||
(DRTIOAUX[linkno].aux_rx_present_write)(1);
|
||||
(DRTIOAUX[linkno].aux_rx_error_write)(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn has_rx_error(linkno: u8) -> bool {
|
||||
let linkno = linkno as usize;
|
||||
unsafe {
|
||||
let error = (DRTIOAUX[linkno].aux_rx_error_read)() != 0;
|
||||
if error {
|
||||
(DRTIOAUX[linkno].aux_rx_error_write)(1)
|
||||
}
|
||||
error
|
||||
}
|
||||
}
|
||||
|
||||
fn receive<F, T>(linkno: u8, f: F) -> Result<Option<T>, Error<!>>
|
||||
where F: FnOnce(&[u8]) -> Result<T, Error<!>>
|
||||
{
|
||||
let linkidx = linkno as usize;
|
||||
unsafe {
|
||||
if (DRTIOAUX[linkidx].aux_rx_present_read)() == 1 {
|
||||
let ptr = DRTIOAUX_MEM[linkidx].base + DRTIOAUX_MEM[linkidx].size / 2;
|
||||
let len = (DRTIOAUX[linkidx].aux_rx_length_read)();
|
||||
let result = f(slice::from_raw_parts(ptr as *mut u8, len as usize));
|
||||
(DRTIOAUX[linkidx].aux_rx_present_write)(1);
|
||||
Ok(Some(result?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recv(linkno: u8) -> Result<Option<Packet>, Error<!>> {
|
||||
if has_rx_error(linkno) {
|
||||
return Err(Error::GatewareError)
|
||||
}
|
||||
|
||||
receive(linkno, |buffer| {
|
||||
if buffer.len() < 8 {
|
||||
return Err(IoError::UnexpectedEnd.into())
|
||||
}
|
||||
|
||||
let mut reader = Cursor::new(buffer);
|
||||
|
||||
let checksum_at = buffer.len() - 4;
|
||||
let checksum = crc::crc32::checksum_ieee(&reader.get_ref()[0..checksum_at]);
|
||||
reader.set_position(checksum_at);
|
||||
if reader.read_u32()? != checksum {
|
||||
return Err(Error::CorruptedPacket)
|
||||
}
|
||||
reader.set_position(0);
|
||||
|
||||
Ok(Packet::read_from(&mut reader)?)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn recv_timeout(linkno: u8, timeout_ms: Option<u64>) -> Result<Packet, Error<!>> {
|
||||
let timeout_ms = timeout_ms.unwrap_or(10);
|
||||
let limit = clock::get_ms() + timeout_ms;
|
||||
while clock::get_ms() < limit {
|
||||
match recv(linkno)? {
|
||||
None => (),
|
||||
Some(packet) => return Ok(packet),
|
||||
}
|
||||
}
|
||||
Err(Error::TimedOut)
|
||||
}
|
||||
|
||||
fn transmit<F>(linkno: u8, f: F) -> Result<(), Error<!>>
|
||||
where F: FnOnce(&mut [u8]) -> Result<usize, Error<!>>
|
||||
{
|
||||
let linkno = linkno as usize;
|
||||
unsafe {
|
||||
while (DRTIOAUX[linkno].aux_tx_read)() != 0 {}
|
||||
let ptr = DRTIOAUX_MEM[linkno].base;
|
||||
let len = DRTIOAUX_MEM[linkno].size / 2;
|
||||
let len = f(slice::from_raw_parts_mut(ptr as *mut u8, len))?;
|
||||
(DRTIOAUX[linkno].aux_tx_length_write)(len as u16);
|
||||
(DRTIOAUX[linkno].aux_tx_write)(1);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(linkno: u8, packet: &Packet) -> Result<(), Error<!>> {
|
||||
transmit(linkno, |buffer| {
|
||||
let mut writer = Cursor::new(buffer);
|
||||
|
||||
packet.write_to(&mut writer)?;
|
||||
|
||||
let padding = 4 - (writer.position() % 4);
|
||||
if padding != 4 {
|
||||
for _ in 0..padding {
|
||||
writer.write_u8(0)?;
|
||||
}
|
||||
}
|
||||
|
||||
let checksum = crc::crc32::checksum_ieee(&writer.get_ref()[0..writer.position()]);
|
||||
writer.write_u32(checksum)?;
|
||||
|
||||
Ok(writer.position())
|
||||
})
|
||||
}
|
5
src/libboard_artiqzynq/lib.rs
Normal file
5
src/libboard_artiqzynq/lib.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod clock;
|
||||
|
||||
#[cfg(has_drtio)]
|
||||
pub mod drtioaux;
|
||||
pub mod drtio_routing;
|
18
src/libproto_artiq/lib.rs
Normal file
18
src/libproto_artiq/lib.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#![no_std]
|
||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||
|
||||
extern crate failure;
|
||||
#[macro_use]
|
||||
extern crate failure_derive;
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
extern crate cslice;
|
||||
#[cfg(feature = "log")]
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
extern crate io;
|
||||
extern crate dyld;
|
||||
|
||||
// Internal protocols.
|
||||
pub mod drtioaux_proto;
|
Loading…
Reference in New Issue
Block a user