| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| use anyhow::Result; |
| use std::path::{Path, PathBuf}; |
| use structopt::StructOpt; |
| use thiserror::Error; |
| |
| use crate::app::config::process_config_file; |
| use crate::app::{TransportWrapper, TransportWrapperBuilder}; |
| use crate::transport::hyperdebug::c2d2::C2d2Flavor; |
| use crate::transport::hyperdebug::{CW310Flavor, StandardFlavor}; |
| use crate::transport::{EmptyTransport, Transport}; |
| use crate::util::parse_int::ParseInt; |
| |
| mod cw310; |
| mod hyperdebug; |
| mod nexus; |
| mod proxy; |
| mod ti50emulator; |
| mod ultradebug; |
| mod verilator; |
| |
| #[derive(Debug, StructOpt)] |
| pub struct BackendOpts { |
| #[structopt(long, default_value = "", help = "Name of the debug interface")] |
| pub interface: String, |
| |
| #[structopt(long, parse(try_from_str = u16::from_str), |
| help="USB Vendor ID of the interface")] |
| pub usb_vid: Option<u16>, |
| #[structopt(long, parse(try_from_str = u16::from_str), |
| help="USB Product ID of the interface")] |
| pub usb_pid: Option<u16>, |
| #[structopt(long, help = "USB serial number of the interface")] |
| pub usb_serial: Option<String>, |
| |
| #[structopt(flatten)] |
| pub cw310_opts: cw310::Cw310Opts, |
| |
| #[structopt(flatten)] |
| pub verilator_opts: verilator::VerilatorOpts, |
| |
| #[structopt(flatten)] |
| pub proxy_opts: proxy::ProxyOpts, |
| |
| #[structopt(flatten)] |
| pub ti50emulator_opts: ti50emulator::Ti50EmulatorOpts, |
| |
| #[structopt(long, number_of_values(1), help = "Configuration files")] |
| pub conf: Vec<PathBuf>, |
| } |
| |
| #[derive(Error, Debug)] |
| pub enum Error { |
| #[error("Unknown interface {0}")] |
| UnknownInterface(String), |
| } |
| |
| /// Creates the requested backend interface according to [`BackendOpts`]. |
| pub fn create(args: &BackendOpts) -> Result<TransportWrapper> { |
| let interface = args.interface.as_str(); |
| let (backend, default_conf) = match interface { |
| "" => (create_empty_transport()?, None), |
| "proxy" => (proxy::create(&args.proxy_opts)?, None), |
| "verilator" => ( |
| verilator::create(&args.verilator_opts)?, |
| Some(Path::new("/__builtin__/opentitan_verilator.json")), |
| ), |
| "ti50emulator" => ( |
| ti50emulator::create(&args.ti50emulator_opts)?, |
| Some(Path::new("/__builtin__/ti50emulator.json")), |
| ), |
| "ultradebug" => ( |
| ultradebug::create(args)?, |
| Some(Path::new("/__builtin__/opentitan_ultradebug.json")), |
| ), |
| "hyper310" => ( |
| hyperdebug::create::<CW310Flavor>(args)?, |
| Some(Path::new("/__builtin__/hyperdebug_cw310.json")), |
| ), |
| "hyperdebug" => (hyperdebug::create::<StandardFlavor>(args)?, None), |
| "hyperdebug_dfu" => (hyperdebug::create_dfu(args)?, None), |
| "c2d2" => ( |
| hyperdebug::create::<C2d2Flavor>(args)?, |
| Some(Path::new("/__builtin__/h1dx_devboard.json")), |
| ), |
| "cw310" => ( |
| cw310::create(args)?, |
| Some(Path::new("/__builtin__/opentitan_cw310.json")), |
| ), |
| "nexus" => ( |
| nexus::create(args)?, |
| Some(Path::new("/__builtin__/nexus.json")), |
| ), |
| _ => return Err(Error::UnknownInterface(interface.to_string()).into()), |
| }; |
| let mut env = TransportWrapperBuilder::new(backend); |
| |
| if args.conf.is_empty() { |
| if let Some(conf_file) = default_conf { |
| process_config_file(&mut env, conf_file)? |
| } |
| } |
| for conf_file in &args.conf { |
| process_config_file(&mut env, conf_file.as_ref())? |
| } |
| env.build() |
| } |
| |
| pub fn create_empty_transport() -> Result<Box<dyn Transport>> { |
| Ok(Box::new(EmptyTransport)) |
| } |