|  | // 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 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")), | 
|  | ), | 
|  | _ => 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)) | 
|  | } |